【发布时间】:2014-01-29 17:09:46
【问题描述】:
编辑:
数据库 - Oracle 11gR2 - 通过 Exadata (X2)
我正在为过去的问题编写问题调查报告,但我对以下情况有点困惑。
说,我有一张桌子MYACCT。有138 列。它拥有10 Million 记录。每小时至少定期更新 1000 条记录(插入/更新/删除)。
主键是COL1 (VARCHAR2(18))(应用程序很少使用这个,除了与其他表的连接)
COL2 VARCHAR2(9)) 上还有另一个唯一索引。这是一个应用程序经常使用。我之前所说的任何更新都是基于这两列发生的。而任何SELECT 仅针对此表的操作,请始终参考COL2。所以COL2 将是我们的兴趣所在。
我们在下面做一个查询,
SELECT COUNT(COL2) FROM MYACCT; /* Use the Unique Column (Not PK) */
结果没有问题,而我是建议将其更改为的人
SELECT COUNT(COL1) FROM MYACCT; /* Use the primary Index
我只是计算了实际执行所需的时间
使用 PRIMARY KEY 的查询总是快 0.8-1.0 秒!
现在,我试图解释这种行为。只是起草这些查询背后的解释计划。
查询 1:(使用主键)
SELECT COUNT(COL1) FROM MYACCT;
计划:
SQL> select * from TABLE(dbms_xplan.display);
Plan hash value: 2417095184
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 11337 (1)| 00:02:17 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX STORAGE FAST FULL SCAN| PK_ACCT | 10M| 11337 (1)| 00:02:17 |
---------------------------------------------------------------------------------
9 rows selected.
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
41332 consistent gets
0 physical reads
0 redo size
210 bytes sent via SQL*Net to client
346 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
查询 2:(不使用主键)
SELECT COUNT(COL2) FROM MYACCT;
计划:
Plan hash value: 1130703739
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 7868 (1)| 00:01:35 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
| 2 | INDEX STORAGE FAST FULL SCAN| MYINDX01 | 10M| 95M| 7868 (1)| 00:01:35 |
------------------------------------------------------------------------------------------
9 rows selected.
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
28151 consistent gets
23 physical reads
784 redo size
233 bytes sent via SQL*Net to client
346 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
我们可以根据
Cost和Time找到无主查询 关键胜利。那么主键的执行时间是怎么来的 更快???
编辑:
SQL> select segment_name, bytes from dba_segments where segment_name in ('MYINDX01','PK_ACCT');
PK_ACCT 343932928
MYINDX01 234881024
【问题讨论】:
-
为什么说select count(*)使用主键?
-
PK和*都给了我相同的计划。计划哈希值是一样的!!反正我的兴趣还是PK。我更新了问题。优化器选择PK进行计数,如果我将其指定为PK或* -
这两列的数据类型是什么?我猜也许更快的查询是针对较小的类型,并且它实际上必须从磁盘读取更少的数据?执行统计显示什么?您还可以查看
dba_segments中两个索引的大小。嗯,等等,你说“使用 PK 查询更快”,但计划似乎相反——你是在谈论计划时间还是实际花费的时间? -
请登录 SQLPlus,运行命令:
SET AUTOTRACE TRACEONLY,然后执行两个查询并将执行结果附加到问题中。 -
@MaheswaranRavisankar 它可能保存着数值,但由于它是一个 varchar2 ,你还不如存储字符串。这是一个非常糟糕的选择,因为即使您分配递增的数字,它们也不会“向右增长”,并且索引将受到 50/50 块拆分而不是更有效的 90/10 块拆分。因此,如果它是数字,您的索引会更小。
标签: sql performance oracle oracle11g exadata