`
844604778
  • 浏览: 551573 次
文章分类
社区版块
存档分类
最新评论

一次SQL分页的优化

 
阅读更多

今天优化了一个分页的SQL,以前虽然做了上千个SQL的优化,不过都是一些OLAP的,虽然也有OLTP的不过从来没做过分页优化,所以这里记录一下。

SQL和执行计划如下:

SQL> SELECT A.ROWNO,EMS_EVENT_VIEW.* FROM EMS_EVENT_VIEW,
  2  (SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY first_occurrence_time DESC) AS ROWNO,EVENT_ID 
  3                    FROM EMS_EVENT_VIEW
                 WHERE (first_occurrence_time>to_date('2012-02-22 00:00:00','yyyy-mm-dd hh24:mi:ss') 
  4    5                            and first_occurrence_time<to_date('2012-02-29 09:42:35','yyyy-mm-dd hh24:mi:ss')) 
                     or (last_occurrence_time>to_date('2012-02-22 00:00:00','yyyy-mm-dd hh24:mi:ss') 
                         and last_occurrence_time<to_date('2012-02-29 09:42:35','yyyy-mm-dd hh24:mi:ss')))
  6    7    8           WHERE ROWNO>=0 AND ROWNO<=20) A
  9  WHERE EMS_EVENT_VIEW.EVENT_ID=A.EVENT_ID;


Plan hash value: 2052413575

-------------------------------------------------------------------------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name                        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |                             |      1 |        |     20 |00:00:53.37 |     757K|       |       |          |
|*  1 |  HASH JOIN                         |                             |      1 |     81G|     20 |00:00:53.37 |     757K|  1179K|  1179K| 6598K (0)|
|*  2 |   VIEW                             |                             |      1 |   2104K|     20 |00:00:30.83 |     101K|       |       |          |
|*  3 |    WINDOW SORT PUSHED RANK         |                             |      1 |   2104K|     21 |00:00:30.83 |     101K|  4096 |  4096 | 4096  (0)|
|*  4 |     FILTER                         |                             |      1 |        |   1255K|00:00:30.10 |     101K|       |       |          |
|   5 |      VIEW                          | EMS_EVENT_VIEW              |      1 |   2104K|   1255K|00:00:28.85 |     101K|       |       |          |
|   6 |       UNION-ALL                    |                             |      1 |        |   1255K|00:00:28.85 |     101K|       |       |          |
|   7 |        CONCATENATION               |                             |      1 |        |      0 |00:00:00.01 |     335 |       |       |          |
|   8 |         TABLE ACCESS BY INDEX ROWID| EMS_EVENT                   |      1 |      1 |      0 |00:00:00.01 |      63 |       |       |          |
|*  9 |          INDEX RANGE SCAN          | LAST_OCCURRENCE_TIME_INDEX  |      1 |      1 |      0 |00:00:00.01 |      63 |       |       |          |
|* 10 |         TABLE ACCESS BY INDEX ROWID| EMS_EVENT                   |      1 |      1 |      0 |00:00:00.01 |     272 |       |       |          |
|* 11 |          INDEX RANGE SCAN          | FIRST_OCCURRENCE_INDEX      |      1 |      1 |      0 |00:00:00.01 |     272 |       |       |          |
|* 12 |        VIEW                        | index_join_006            |      1 |   2104K|   1255K|00:00:28.84 |     100K|       |       |          |
|* 13 |         HASH JOIN                  |                             |      1 |        |   3863K|00:00:26.50 |     100K|   195M|     9M|  248M (0)|
|* 14 |          HASH JOIN                 |                             |      1 |        |   3863K|00:00:13.87 |   63020 |   160M|    10M|  214M (0)|
|  15 |           PARTITION RANGE ALL      |                             |      1 |   2104K|   3863K|00:00:00.01 |   31419 |       |       |          |
|  16 |            INDEX FAST FULL SCAN    | IDX_FIRSTTIME_201202        |    338 |   2104K|   3863K|00:00:00.07 |   31419 |       |       |          |
|  17 |           PARTITION RANGE ALL      |                             |      1 |   2104K|   3863K|00:00:00.01 |   31601 |       |       |          |
|  18 |            INDEX FAST FULL SCAN    | IDX_LASTOCCURRENCE_201202   |    338 |   2104K|   3863K|00:00:00.06 |   31601 |       |       |          |
|  19 |          INDEX FAST FULL SCAN      | PK_EMS_EVENT_HISTORY_201202 |      1 |   2104K|   3863K|00:00:00.01 |   37894 |       |       |          |
|  20 |   VIEW                             | EMS_EVENT_VIEW              |      1 |   3864K|   3867K|00:00:19.34 |     656K|       |       |          |
|  21 |    UNION-ALL                       |                             |      1 |        |   3867K|00:00:15.47 |     656K|       |       |          |
|  22 |     TABLE ACCESS FULL              | EMS_EVENT                   |      1 |   3867 |   3950 |00:00:00.02 |    2046 |       |       |          |
|  23 |     PARTITION RANGE ALL            |                             |      1 |   3860K|   3863K|00:00:07.73 |     654K|       |       |          |
|  24 |      TABLE ACCESS FULL             | EMS_EVENT_HISTORY           |    338 |   3860K|   3863K|00:00:09.51 |     654K|       |       |          |
-------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("EMS_EVENT_VIEW"."EVENT_ID"="from_subquery_003"."EVENT_ID")
   2 - filter(("ROWNO">=:SYS_B_8 AND "ROWNO"<=:SYS_B_9))
   3 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("FIRST_OCCURRENCE_TIME") DESC )<=:SYS_B_9)
   4 - filter(:SYS_B_8<=:SYS_B_9)
   9 - access("A"."LAST_OCCURRENCE_TIME">TO_DATE(:SYS_B_4,:SYS_B_5) AND "A"."LAST_OCCURRENCE_TIME"<TO_DATE(:SYS_B_6,:SYS_B_7))
  10 - filter((LNNVL("A"."LAST_OCCURRENCE_TIME"<TO_DATE(:SYS_B_6,:SYS_B_7)) OR LNNVL("A"."LAST_OCCURRENCE_TIME">TO_DATE(:SYS_B_4,:SYS_B_5))))
  11 - access("A"."FIRST_OCCURRENCE_TIME">TO_DATE(:SYS_B_0,:SYS_B_1) AND "A"."FIRST_OCCURRENCE_TIME"<TO_DATE(:SYS_B_2,:SYS_B_3))
  12 - filter((("B"."FIRST_OCCURRENCE_TIME">TO_DATE(:SYS_B_0,:SYS_B_1) AND "B"."FIRST_OCCURRENCE_TIME"<TO_DATE(:SYS_B_2,:SYS_B_3)) OR
              ("B"."LAST_OCCURRENCE_TIME">TO_DATE(:SYS_B_4,:SYS_B_5) AND "B"."LAST_OCCURRENCE_TIME"<TO_DATE(:SYS_B_6,:SYS_B_7))))
  13 - access(ROWID=ROWID)
  14 - access(ROWID=ROWID)


如果你看不清楚SQL,我在这里再贴一下:

SELECT A.ROWNO, EMS_EVENT_VIEW.*
FROM EMS_EVENT_VIEW,
(SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY first_occurrence_time DESC) AS ROWNO,
EVENT_ID
FROM EMS_EVENT_VIEW
WHERE (first_occurrence_time >
to_date('2012-02-22 00:00:00',
'yyyy-mm-dd hh24:mi:ss') and
first_occurrence_time <
to_date('2012-02-29 09:42:35',
'yyyy-mm-dd hh24:mi:ss'))
))
WHERE ROWNO >= 0
AND ROWNO <= 20) A
WHERE EMS_EVENT_VIEW.EVENT_ID = A.EVENT_ID;

这个SQL其实就是一个分页SQL,利用 row_number over 做分页,EMS_EVENT_VIEW是一个视图。这个SQL确实写得很坑爹,它要扫描EMS_EVENT_VIEW两次,其实我们可以改写它,让它扫描一次,而不是自己和自己利用event_id 做自连接。

EMS_EVENT_VIEW的定义就不贴出来了,涉及保密。它的大概意思就是 select * from a union all select * from b; 无where 过滤条件。

因为这个SQL是朋友给我的,我无法连接到他的DB,所以我只有自己做测试了,测试代码如下:

create table a as select * from dba_objects;
create table b as select * from dba_objects;

create view test_view as select * from a
union all select * from b;

create index idx_a on a(created ,last_ddl_time);
create index idx_b on b(created ,last_ddl_time);

BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
tabname => 'B',
estimate_percent => 100,
method_opt => 'for all columns size auto',
no_invalidate => FALSE,
degree => 4,
cascade => TRUE);
END;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
tabname => 'B',
estimate_percent => 100,
method_opt => 'for all columns size auto',
no_invalidate => FALSE,
degree => 4,
cascade => TRUE);
END;
/

要优化的SQL可以改写成如下代码,只访问一次视图:

select * from
(
select t.*,rownum rn from
(select /*+ INDEX(TEST_VIEW.A idx_a) INDEX(TEST_VIEW.b idx_b) */ *
from test_view
where created > to_date('2010-01-01', 'yyyy-mm-dd') or
LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
order by created desc
) t where rownum<=20
) where rn>=0;

现在来看它的执行计划

SQL> select * from
  2  (
  3  select t.*,rownum rn from
  4  (select /*+ INDEX(TEST_VIEW.A idx_a) INDEX(TEST_VIEW.b idx_b) */ *
  5    from test_view
  6   where created > to_date('2010-01-01', 'yyyy-mm-dd') or
  7         LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
  8   order by created desc
  9  ) t where rownum<=20
 10  ) where rn>=0;

已选择20行。

已用时间:  00: 00: 00.10

执行计划
----------------------------------------------------------
Plan hash value: 1808710389

-------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |           |    20 |  3800 |       |  1898   (2)| 00:00:23 |
|*  1 |  VIEW                             |           |    20 |  3800 |       |  1898   (2)| 00:00:23 |
|*  2 |   COUNT STOPKEY                   |           |       |       |       |            |          |
|   3 |    VIEW                           |           | 70304 |    11M|       |  1898   (2)| 00:00:23 |
|*  4 |     SORT ORDER BY STOPKEY         |           | 70304 |  6659K|    17M|  1898   (2)| 00:00:23 |
|   5 |      VIEW                         | TEST_VIEW | 70304 |  6659K|       |   329   (5)| 00:00:04 |
|   6 |       UNION-ALL PARTITION         |           |       |       |       |            |          |
|   7 |        TABLE ACCESS BY INDEX ROWID| A         |  1650 |   156K|       |   238   (3)| 00:00:03 |
|*  8 |         INDEX FULL SCAN           | IDX_A     |  1650 |       |       |   199   (4)| 00:00:03 |
|   9 |        TABLE ACCESS BY INDEX ROWID| B         |  1650 |   156K|       |   238   (3)| 00:00:03 |
|* 10 |         INDEX FULL SCAN           | IDX_B     |  1650 |       |       |   199   (4)| 00:00:03 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">=0)
   2 - filter(ROWNUM<=20)
   4 - filter(ROWNUM<=20)
   8 - filter("CREATED">TO_DATE('2010-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "LAST_DDL_TIME"<TO_DATE('2007-0101','yyyy-mm-dd'))
  10 - filter("CREATED">TO_DATE('2010-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "LAST_DDL_TIME"<TO_DATE('2007-0101','yyyy-mm-dd'))


统计信息
----------------------------------------------------------
          8  recursive calls
          0  db block gets
        566  consistent gets
          9  physical reads
          0  redo size
       2621  bytes sent via SQL*Net to client
        411  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
         20  rows processed

逻辑读566,那么这样改写是不是最优化的呢?显然不是,因为索引 IDX_A,IDX_B 都是走的 index full scan,会扫描整个索引block,原始的SQL这个索引里面有3863K 条数据,性能肯定是很低的。 所以进一步的 改写SQL 如下:
select * from
(
select t.*,rownum rn from
(
select * from
(select * from
(
select /*+ index_desc(a) */ *
from a
where created > to_date('2010-01-01', 'yyyy-mm-dd') or
LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
order by created desc
) where rownum<=20
union all
select * from
(
select /*+ index_desc(b) */ *
from b
where created > to_date('2010-01-01', 'yyyy-mm-dd') or
LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
order by created desc
) where rownum<=20
) order by created desc
) t where rownum<=20
) where rn>=0


执行计划和逻辑读如下:

SQL> select * from
  2  (
  3  select t.*,rownum rn from
  4  (
  5  select * from
  6  (select * from
  7  (
  8  select /*+ index_desc(a) */ *
  9    from a
 10   where created > to_date('2010-01-01', 'yyyy-mm-dd') or
 11         LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
 12   order by created desc
 13  ) where rownum<=20
 14  union all
 15  select * from
 16  (
 17  select /*+ index_desc(b) */ *
 18    from b
 19   where created > to_date('2010-01-01', 'yyyy-mm-dd') or
 20         LAST_DDL_TIME < to_date('2007-0101', 'yyyy-mm-dd')
 21   order by created desc
 22  ) where rownum<=20
 23  ) order by created desc
 24  ) t where rownum<=20
 25  ) where rn>=0;

已选择20行。

已用时间:  00: 00: 00.04

执行计划
----------------------------------------------------------
Plan hash value: 3460309830

---------------------------------------------------------------------------------------------
| Id  | Operation                           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |       |    20 |  3800 |   244   (4)| 00:00:03 |
|*  1 |  VIEW                               |       |    20 |  3800 |   244   (4)| 00:00:03 |
|*  2 |   COUNT STOPKEY                     |       |       |       |            |          |
|   3 |    VIEW                             |       |    40 |  7080 |   244   (4)| 00:00:03 |
|*  4 |     SORT ORDER BY STOPKEY           |       |    40 |  7080 |   244   (4)| 00:00:03 |
|   5 |      VIEW                           |       |    40 |  7080 |   243   (3)| 00:00:03 |
|   6 |       UNION-ALL                     |       |       |       |            |          |
|*  7 |        COUNT STOPKEY                |       |       |       |            |          |
|   8 |         VIEW                        |       |  1650 |   285K|   238   (3)| 00:00:03 |
|   9 |          TABLE ACCESS BY INDEX ROWID| A     |  1650 |   156K|   238   (3)| 00:00:03 |
|* 10 |           INDEX FULL SCAN DESCENDING| IDX_A |  1650 |       |   199   (4)| 00:00:03 |
|* 11 |        COUNT STOPKEY                |       |       |       |            |          |
|  12 |         VIEW                        |       |    20 |  3540 |     5   (0)| 00:00:01 |
|  13 |          TABLE ACCESS BY INDEX ROWID| B     |    20 |  1940 |     5   (0)| 00:00:01 |
|* 14 |           INDEX FULL SCAN DESCENDING| IDX_B |  1650 |       |     4   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">=0)
   2 - filter(ROWNUM<=20)
   4 - filter(ROWNUM<=20)
   7 - filter(ROWNUM<=20)
  10 - filter("CREATED">TO_DATE('2010-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "LAST_DDL_TIME"<TO_DATE('2007-0101','yyyy-mm-dd'))
  11 - filter(ROWNUM<=20)
  14 - filter("CREATED">TO_DATE('2010-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "LAST_DDL_TIME"<TO_DATE('2007-0101','yyyy-mm-dd'))


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         10  consistent gets
          0  physical reads
          0  redo size
       2457  bytes sent via SQL*Net to client
        411  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
         20  rows processed


逻辑读整整下降了60倍。

现在根据这个案例来谈谈SQL分页的优化思路,SQL分页通常要进行排序,比如select xxxx from t where 条件 order by ......

优化分页SQL可以重点关注 order by 这个条件,写SQL的时候要让ORACLE 对 order by 列 上的索引进行有序的扫描,然后根据stopkey 停止,也就是不要把索引的block全都给扫描了,应该扫描一部分block就停止。

分享到:
评论

相关推荐

    收获不止SQL优化

    11.3.3 一次 Merge Sort Join 的优化全过程 324 11.3.4 一次统计信息收集不准确引发的NL性能瓶颈 329 11.4 本章习题、总结与延伸 332 第12章 动手,经典等价改写让SQL飞 333 12.1 设法减少访问路径 333 12.1.1...

    收获,不止SQL优化--抓住SQL的本质

    11.3.3 一次 Merge Sort Join 的优化全过程 324 11.3.4 一次统计信息收集不准确引发的NL性能瓶颈 329 11.4 本章习题、总结与延伸 332 第12章 动手,经典等价改写让SQL飞 333 12.1 设法减少访问路径 333 12.1.1...

    mysql 分页优化解析

     SQL数据库分页:用存储过程+游标方式分页,具体实现原理不是很清楚,设想如果用一次查询就得到需要的结果,或者是id集,需要后续页时只要按照结果中的IDs读出相关记录。这样只要很小的空间保留本次查询的所有IDs....

    mybatis查询分页插件

    实现原理为mybatis的拦截器,但是比网上目前流行的修行sql方式优化,只是第一次调用查询时需要处理,以后不需要再额外处理。 生成的sql为自动化的最优(基于数据绑定方式的sql)。 缺点: 扩展需要对mybatis源码...

    mysql分页时offset过大的Sql优化经验分享

    当我们展示一个列表中的内容时,难免会遇到分页问题,因为列表中的内容数量可能很多,但是用户能一次看到的界面大小是有限的,不可能一个界面展示所有的内容,从后端一次性取太多的数据也会给后端造成额外的压力。...

    MySQL百万级数据量分页查询方法及其优化建议

    数据库SQL优化是老生常谈的问题,在面对百万级数据量的分页查询,又有什么好的优化建议呢?下面将列举了一些常用的方法,供大家参考学习! 方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: ...

    Microsoft SQL Server 2008技术内幕:T-SQL查询(第二卷)

     作为一本讲述T-SQL高级查询的专业图书,《Microsoft SQL Server 2008技术内幕:T-SQL查询》旨在结合实践中的各种常见问题,教读者如何用SQL作为语言工具来思考问题,揭示基于集合查询的强大威力。《Microsoft SQL ...

    SQLServer2008技术内幕T-SQL查询包含源代码及附录A

    《Microsoft SQL Server 2008技术内幕:T-SQL查询》全面深入地介绍了Microsoft SQL Server 2008中高级T-SQL查询、性能优化等方面的内容,以及SQL Server 2008新增加的一些特性。主要内容包括SQL的基础理论、查询优化...

    MySQL百万级数据分页查询优化方案

    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。下面简单说一下我知道的一些...

    MySQL中的回表查询与索引覆盖:一次百万级别分页查询使用Limit 从90秒到0.6毫秒的优化

    数据库使用的MySQL,有一个日志表,需要进行分页查询,于是很容易就想到了limit [offset偏移量] [count数量]这个查询方式,当我们偏移量比较小时,似乎是没什么问题 SELECT * FROM t_log WHERE type = 1 LIMIT 5, 50 ...

    Microsoft+SQL+Server+2008技术内幕:T-SQL查询_源代码及附录 中文版

    《Microsoft SQL Server 2008技术内幕:T-SQL查询》全面深入地介绍了Microsoft SQL Server 2008中高级T-SQL查询、性能优化等方面的内容,以及SQL Server 2008新增加的一些特性。主要内容包括SQL的基础理论、查询优化...

    《Oracle DBA手记——数据库诊断案例与性能优化实践》第一章 to be continued

    ├─第一篇 DBA工作手记 │ 01.Eygle的DBA工作手记 │ 02.Yangtingkun的DBA工作手记 │ 03.老熊的DBA手记 │ 04.BanPing的DBA工作手记 │ ├─第二篇 诊断案例篇 │ 01.ASM案例分析与诊断 ...一次排序的调整与优化

    SQLServer的性能调优:解决查询速度慢的五种方法

    本文主要通过一下几个方面介绍:使用SQL DMV查找慢速查询、通过APM解决方案查询报告、...SQLServer的一个重要功能是内置于其中的所有动态管理视图(DMV)。它们有数十种,可以提供有关各种主题的丰富信息。有几个DMV提

    MySQL分页技术、6种分页方法总结

    原因/缺点: 全表扫描,速度会很慢 且 有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是从结果集的M位置处取出N条输出,其余抛弃. 方法2: 建立主键或唯一索引, 利用索引(假设每页10条)...

    8种MySQL分页方法总结

    —原因/缺点: 全表扫描,速度会很慢 且 有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3)。Limit限制的是从结果集的M位置处取出N条输出,其余抛弃。 方法2: 建立主键或唯一索引, 利用索引(假设每页10...

    计算机课程设计+ACCESS/SQL+学生成绩管理系统

    统计所有表内信息,得出行数,以行数进行数据分页(目的:由于数据的日渐增多,而所有数据一次性显示在表格内,会影响系统的正常使用,分页则是将众多数据一点点的显示出来,达到资源优化的目的.) (5).开始根据分页内容给...

    paginator:Paginator很简单,可以在应用程序中生成结果导航(结果分页已解耦,并且易于与SQL集成)

    您只需通过计数器配置一次其行为,然后使用render方法通过所有导航链接创建导航。 轻松地使用咖啡并与您的数据库进行交互。 分页器是一种非常紧凑且易于使用的组件。 您只需由构建器配置一次您的行为,然后使用...

    Oracle查询总结与优化

    procedure sp_Page(p_PageSize int, --每页记录数 p_PageNo int, --当前页码,从 1 开始 ... --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn OPEN p_OutCursor FOR v_sql; end sp_Page;

    最好的asp CMS系统科讯CMSV7.0全功能SQL商业版,KesionCMS V7.0最新商业全能版-免费下载

    这种好处当您的栏目下有上万篇文章时越是明显,因为每次生成时不需要将所有页面重新生成一次,只需要根据预设定的生成最新更新的记录即可! 3、 系统由文章、图片、下载、分类信息、商城、求职招聘、影视、动漫...

    易点内容管理系统 DianCMS v5.3.0 SQL

    20、终极列表内置24种分页效果,满足不同网站风格 21、集成文章系统、下载系统.使用导入模型功能,可增加多种系统功能 22、数据字典内置多种常用类别:*地区、个人爱好、评分等级等 23、站内链接功能 24、特殊...

Global site tag (gtag.js) - Google Analytics