Oracle 如何获得计数(col)。。。分组方式以使用索引?
我有一张桌子col1,col2。。。在col1,col2。。。。表中有数百万行,我想运行一个查询:Oracle 如何获得计数(col)。。。分组方式以使用索引?,oracle,group-by,indexing,query-optimization,Oracle,Group By,Indexing,Query Optimization,我有一张桌子col1,col2。。。在col1,col2。。。。表中有数百万行,我想运行一个查询: SELECT col1, COUNT(col2) WHERE col1 NOT IN (<couple of exclusions>) GROUP BY col1 SYS.OBJ$SYS.I_OBJ2上有一个索引,它对owner和name列进行索引;我相信我应该能够在查询中使用此索引,而不是对SYS.OBJ$进行完整的表扫描, 但请记住,使用索引可能并不总是导致更快的执行 以防万一
SELECT col1, COUNT(col2) WHERE col1 NOT IN (<couple of exclusions>) GROUP BY col1
SYS.OBJ$SYS.I_OBJ2上有一个索引,它对owner和name列进行索引;我相信我应该能够在查询中使用此索引,而不是对SYS.OBJ$进行完整的表扫描,
但请记住,使用索引可能并不总是导致更快的执行 以防万一,您确定它正在进行表扫描而不是索引扫描吗
当然,如果这适合您的问题,请尝试使用COUNT*而不是COUNTcol2。另外,也许可以尝试只使用col1的索引。我曾经有机会尝试过这一点,而我之前关于NOT IN的评论在这种情况下是一种误导。关键是是否存在空值,或者更确切地说,索引列是否没有强制执行空约束 这将取决于您使用的数据库版本,因为优化器在每个版本中都会变得更智能。我使用的是11gR1,优化器在所有情况下都使用了索引,只有一种情况除外:当两列都为null且我没有包含NOT in子句时: 如果没有NOT IN子句
SQL> explain plan for
2 select col4, count(col1) from big_table
3 group by col4
4 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 1753714399
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 7574 (2)| 00:01:31 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 7574 (2)| 00:01:31 |
| 2 | TABLE ACCESS FULL| BIG_TABLE | 2340K| 20M| | 4284 (1)| 00:00:52 |
----------------------------------------------------------------------------------------
9 rows selected.
SQL>
当我将NOT IN子句重新插入时,优化器选择使用索引。奇怪
SQL> explain plan for
2 select col4, count(col1) from big_table
3 where col1 not in (12, 19)
4 group by col4
5 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 343952376
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 5057 (3)| 00:01:01 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 5057 (3)| 00:01:01 |
|* 2 | INDEX FAST FULL SCAN| BIG_I2 | 2340K| 20M| | 1767 (2)| 00:00:22 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
2 - filter("COL1"<>12 AND "COL1"<>19)
14 rows selected.
SQL>
重复一次,在所有其他情况下,只要其中一个索引列被声明为not nill,索引就用于满足查询。这在早期版本的Oracle上可能不正确,但它可能指明了前进的方向。您正在查询Oracle的固定表,因为您没有说明这是哪一个db vesion,我假设是最近的一个。是否对固定表进行了分析并更新了统计数据?您是否使用/*+规则*/hint使用规则库优化器尝试过查询。我经常看到,当使用规则库优化器时,针对oracle自己的固定表的查询执行得更好。删除NOT IN STALL会导致对表进行完整的表扫描,查询计划中的表访问权限已满,成本为2200。我不能在上面创建索引,但是col1,col2。。。对于针对col1的查询,是否与col1上的索引相同?
SQL> explain plan for
2 select col4, count(col1) from big_table
3 group by col4
4 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 1753714399
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 7574 (2)| 00:01:31 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 7574 (2)| 00:01:31 |
| 2 | TABLE ACCESS FULL| BIG_TABLE | 2340K| 20M| | 4284 (1)| 00:00:52 |
----------------------------------------------------------------------------------------
9 rows selected.
SQL>
SQL> explain plan for
2 select col4, count(col1) from big_table
3 where col1 not in (12, 19)
4 group by col4
5 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 343952376
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 5057 (3)| 00:01:01 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 5057 (3)| 00:01:01 |
|* 2 | INDEX FAST FULL SCAN| BIG_I2 | 2340K| 20M| | 1767 (2)| 00:00:22 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
2 - filter("COL1"<>12 AND "COL1"<>19)
14 rows selected.
SQL>