表结构:
CREATE TABLE TB_RID_TRACE_2013
(
ID VARCHAR2(50) NOT NULL CONSTRAINT PK_TB_RID_TRACE_2013 PRIMARY KEY,
SESSION_ID VARCHAR2(50),
LOGIN_AT DATE,
LOGOUT_AT DATE,
ID_TYPE VARCHAR2(32),
ID_CODE VARCHAR2(100),
ID_NAME VARCHAR2(100),
AREA_CODE VARCHAR2(15),
SERVICE_CODE VARCHAR2(32),
SERVICE_WAN_IP VARCHAR2(32),
SERVICE_LAN_IP VARCHAR2(32),
SERVICE_MAC VARCHAR2(32),
HOST_NAME VARCHAR2(100)
)
PARTITION BY RANGE (LOGIN_AT)
(
PARTITION TB_RID_TRACE_2013_PART_01 VALUES LESS THAN (TO_DATE('2013-02-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_02 VALUES LESS THAN (TO_DATE('2013-03-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_03 VALUES LESS THAN (TO_DATE('2013-04-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_04 VALUES LESS THAN (TO_DATE('2013-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_05 VALUES LESS THAN (TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_06 VALUES LESS THAN (TO_DATE('2013-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_07 VALUES LESS THAN (TO_DATE('2013-08-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_08 VALUES LESS THAN (TO_DATE('2013-09-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_09 VALUES LESS THAN (TO_DATE('2013-10-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_10 VALUES LESS THAN (TO_DATE('2013-11-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_11 VALUES LESS THAN (TO_DATE('2013-12-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_12 VALUES LESS THAN (TO_DATE('2014-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))
)
NOLOGGING;该表上创建的索引:
CREATE INDEX IDX_2013_ID_CODE ON TB_RID_TRACE_2013 (ID_CODE DESC);CREATE INDEX IDX_2013_LOGIN_AT ON TB_RID_TRACE_2013 (LOGIN_AT DESC);CREATE INDEX IDX_2013_LOGOUT_AT ON TB_RID_TRACE_2013 (LOGOUT_AT DESC);CREATE INDEX IDX_2013_SERVICE_CODE ON TB_RID_TRACE_2013 (SERVICE_CODE DESC);
目前表里有18000000条数据,系统里是使用ExtJS分页显示列表。问题是执行普通SQL速度很快。但是如果SQL里包含Order By后速度就变得爆慢。以下是我执行的SQL和时间以及执行计划的内容:
SQL1,执行时间:0.172秒100条数据
SELECT * FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS');SQL1执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 3349134993------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 255M| 19128 (2)| 00:03:50 | | |
| 1 | PARTITION RANGE SINGLE| | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
|* 2 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
SQL2,执行时间:14.789秒100条数据
SELECT T.* FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY T.LOGIN_AT;SQL2执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 2801453287--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 255M| | 78265 (1)| 00:15:40 | | |
| 1 | PARTITION RANGE SINGLE| | 1555K| 255M| | 78265 (1)| 00:15:40 | 6 | 6 |
| 2 | SORT ORDER BY | | 1555K| 255M| 607M| 78265 (1)| 00:15:40 | | |
|* 3 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
--------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 3 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))SQL3,执行时间:24.492秒100条数据
SELECT * FROM (SELECT ROWNUM RN, T.* FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY T.LOGIN_AT DESC) T2 WHERE T2.RN BETWEEN 0 AND 100;SQL3执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 283752969-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
|* 1 | VIEW | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
| 2 | SORT ORDER BY | | 1555K| 255M| 607M| 78265 (1)| 00:15:40 | | |
| 3 | COUNT | | | | | | | | |
| 4 | PARTITION RANGE SINGLE| | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
|* 5 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
-----------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("T2"."RN"<=100 AND "T2"."RN">=0)
5 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))Oracle10gOrder by速度慢优化索引
CREATE TABLE TB_RID_TRACE_2013
(
ID VARCHAR2(50) NOT NULL CONSTRAINT PK_TB_RID_TRACE_2013 PRIMARY KEY,
SESSION_ID VARCHAR2(50),
LOGIN_AT DATE,
LOGOUT_AT DATE,
ID_TYPE VARCHAR2(32),
ID_CODE VARCHAR2(100),
ID_NAME VARCHAR2(100),
AREA_CODE VARCHAR2(15),
SERVICE_CODE VARCHAR2(32),
SERVICE_WAN_IP VARCHAR2(32),
SERVICE_LAN_IP VARCHAR2(32),
SERVICE_MAC VARCHAR2(32),
HOST_NAME VARCHAR2(100)
)
PARTITION BY RANGE (LOGIN_AT)
(
PARTITION TB_RID_TRACE_2013_PART_01 VALUES LESS THAN (TO_DATE('2013-02-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_02 VALUES LESS THAN (TO_DATE('2013-03-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_03 VALUES LESS THAN (TO_DATE('2013-04-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_04 VALUES LESS THAN (TO_DATE('2013-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_05 VALUES LESS THAN (TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_06 VALUES LESS THAN (TO_DATE('2013-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_07 VALUES LESS THAN (TO_DATE('2013-08-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_08 VALUES LESS THAN (TO_DATE('2013-09-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_09 VALUES LESS THAN (TO_DATE('2013-10-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_10 VALUES LESS THAN (TO_DATE('2013-11-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_11 VALUES LESS THAN (TO_DATE('2013-12-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')),
PARTITION TB_RID_TRACE_2013_PART_12 VALUES LESS THAN (TO_DATE('2014-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))
)
NOLOGGING;该表上创建的索引:
CREATE INDEX IDX_2013_ID_CODE ON TB_RID_TRACE_2013 (ID_CODE DESC);CREATE INDEX IDX_2013_LOGIN_AT ON TB_RID_TRACE_2013 (LOGIN_AT DESC);CREATE INDEX IDX_2013_LOGOUT_AT ON TB_RID_TRACE_2013 (LOGOUT_AT DESC);CREATE INDEX IDX_2013_SERVICE_CODE ON TB_RID_TRACE_2013 (SERVICE_CODE DESC);
目前表里有18000000条数据,系统里是使用ExtJS分页显示列表。问题是执行普通SQL速度很快。但是如果SQL里包含Order By后速度就变得爆慢。以下是我执行的SQL和时间以及执行计划的内容:
SQL1,执行时间:0.172秒100条数据
SELECT * FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS');SQL1执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 3349134993------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 255M| 19128 (2)| 00:03:50 | | |
| 1 | PARTITION RANGE SINGLE| | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
|* 2 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
SQL2,执行时间:14.789秒100条数据
SELECT T.* FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY T.LOGIN_AT;SQL2执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 2801453287--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 255M| | 78265 (1)| 00:15:40 | | |
| 1 | PARTITION RANGE SINGLE| | 1555K| 255M| | 78265 (1)| 00:15:40 | 6 | 6 |
| 2 | SORT ORDER BY | | 1555K| 255M| 607M| 78265 (1)| 00:15:40 | | |
|* 3 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
--------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 3 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))SQL3,执行时间:24.492秒100条数据
SELECT * FROM (SELECT ROWNUM RN, T.* FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY T.LOGIN_AT DESC) T2 WHERE T2.RN BETWEEN 0 AND 100;SQL3执行计划:
执行计划
----------------------------------------------------------
Plan hash value: 283752969-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
|* 1 | VIEW | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
| 2 | SORT ORDER BY | | 1555K| 255M| 607M| 78265 (1)| 00:15:40 | | |
| 3 | COUNT | | | | | | | | |
| 4 | PARTITION RANGE SINGLE| | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
|* 5 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
-----------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("T2"."RN"<=100 AND "T2"."RN">=0)
5 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))Oracle10gOrder by速度慢优化索引
解决方案 »
- 模糊匹配的问题 急---
- redhat as6 x64 上安装oracle 10g X64 问题
- 请问在PL/SQL里怎么看oracle自带的虚拟表的名字,像有的虚拟表叫dual 有的又是其他的 谢谢
- 触发器不能执行语句: alter sequence Seq_Kf02_Pzbh maxvalue 9;
- 如何优化大数据表的LEFTJOIN
- 有人可以给我一些,ORACLE开发中常用的函数吗?
- 哪儿有 oracle oci 的书籍或资料下载???
- 谁在导入数据时遇见过这个错误,ORA-24810: 正在尝试写入多于指定的数据
- 请问如何在8.17中建一个只拥有查询权限的用户 ?
- oracle 可以存放xml文件吗,怎么实现?
- 生手提问: 请问怎么以 sysdba登录到sql plus中?
- .net中怎么样来调用包中的函数?
为条件返回多少条记录?从查询计划上看返回1555K
真实有那么多吗?看看是否要收集一些统计信息?
SELECT * FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS');已选择1618063行。已用时间: 00: 05: 12.15执行计划
----------------------------------------------------------
Plan hash value: 3349134993------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 255M| 19128 (2)| 00:03:50 | | |
| 1 | PARTITION RANGE SINGLE| | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
|* 2 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| 19128 (2)| 00:03:50 | 6 | 6 |
------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
统计信息
----------------------------------------------------------
284 recursive calls
0 db block gets
191262 consistent gets
59213 physical reads
0 redo size
288375280 bytes sent via SQL*Net to client
1186970 bytes received via SQL*Net from client
107872 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1618063 rows processed
SELECT * FROM (SELECT ROWNUM RN, T.* FROM TB_RID_TRACE_2013 T WHERE T.LOGIN_AT BETWEEN TO_DATE('2013-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2013-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY T.LOGIN_AT DESC) T2 WHERE T2.RN BETWEEN 0 AND 100;已选择100行。已用时间: 00: 00: 18.38执行计划
----------------------------------------------------------
Plan hash value: 283752969-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
|* 1 | VIEW | | 1555K| 504M| | 78265 (1)| 00:15:40 | | |
| 2 | SORT ORDER BY | | 1555K| 255M| 607M| 78265 (1)| 00:15:40 | | |
| 3 | COUNT | | | | | | | | |
| 4 | PARTITION RANGE SINGLE| | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
|* 5 | TABLE ACCESS FULL | TB_RID_TRACE_2013 | 1555K| 255M| | 19128 (2)| 00:03:50 | 6 | 6 |
-----------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("T2"."RN"<=100 AND "T2"."RN">=0)
5 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
统计信息
----------------------------------------------------------
317 recursive calls
14 db block gets
85985 consistent gets
104994 physical reads
0 redo size
19157 bytes sent via SQL*Net to client
466 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
1 sorts (disk)
100 rows processed
PGA和SGA设置都很大,都是5G
是不是索引没用到?难道索引创建多了?索引是我后来追加的,当时表里已经有这么多数据了,我也REBUILD了啊!
1)5 - filter("T"."LOGIN_AT"<=TO_DATE('2013-06-15 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
==> 存在隐式类型转换!太槽糕了
2) 2 | TABLE ACCESS FULL | TB_RID_TRACE_2013
==> CBO选择全表扫、索引在这里不起作用
3)既然分区了、干嘛还选择全局索引?
4)1 sorts (disk)
==> 都跑到磁盘上来排序了?pga里面sort_area多大?
5)索引是我后来追加的,当时表里已经有这么多数据了,我也REBUILD了啊!
==> 表和索引的统计信息重新收集了没?
pga大小是6G,sort_area是什么东西?怎么查看和设置?表和索引的统计信息怎么收集?
斑竹,再指点指点呗O(∩_∩)O~
2)表信息收集:dbms_stats.gather_table_stats
索引信息收集:dbms_stats.gather_index_stats
3)用了分区就建议用分区索引(即:本地索引)、全局索引一般没啥效果吧
另外、根据你4楼贴出的语句 已选择1618063行 1百多万行啊 返回这么多的数量 在sql方面作优化空间非常少了
我想做的功能是分页的,但是这个SQL作为子查询的时候,确实是慢,有没有其他好的优化方案啊?关于分页的?Rows为什么没有值,我也不知道!“是直方图问题?统计信息问题?还是高水位问题?”不懂O(∩_∩)O~
2)表信息收集:dbms_stats.gather_table_stats
索引信息收集:dbms_stats.gather_index_stats
3)用了分区就建议用分区索引(即:本地索引)、全局索引一般没啥效果吧
谢谢给的优化建议O(∩_∩)O~另外,表信息收集和索引信息收集,有什么作用?能提高效率还是只是作为开发人员分析的?
2)分页用rownum来分吧、Oracle CBO分页优化已经很智能了、