我有一个查询,在我认为可能不使用索引的情况下,出于好奇,我将其重现:
创建一个test_table
具有1.000.000行(在中有10个不同的值,在col
中有500个字节的数据some_data
)的。
CREATE TABLE test_table AS (
SELECT MOD(ROWNUM,10) col, LPAD('x', 500, 'x') some_data
FROM dual
CONNECT BY ROWNUM <= 1000000
);
创建一个索引并收集表统计信息:
CREATE INDEX test_index ON test_table ( col );
EXEC dbms_stats.gather_table_stats( 'MY_SCHEMA', 'TEST_TABLE' );
尝试获取col
和的不同值COUNT
:
EXPLAIN PLAN FOR
SELECT col, COUNT(*)
FROM test_table
GROUP BY col;
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 30 | 15816 (1)| 00:03:10
| 1 | HASH GROUP BY | | 10 | 30 | 15816 (1)| 00:03:10
| 2 | TABLE ACCESS FULL| TEST_TABLE | 994K| 2914K| 15755 (1)| 00:03:10
---------------------------------------------------------------------------------
不使用索引,前提是提示不会更改。
我想在这种情况下不能使用索引,但是为什么呢?
我运行了Peter的原始内容并复制了他的结果。然后我应用了dcp的建议…
SQL> alter table test_table modify col not null;
Table altered.
SQL> EXEC dbms_stats.gather_table_stats( user, 'TEST_TABLE' , cascade=>true)
PL/SQL procedure successfully completed.
SQL> EXPLAIN PLAN FOR
2 SELECT col, COUNT(*)
3 FROM test_table
4 GROUP BY col;
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan html" target="_blank">hash value: 2099921975
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 30 | 574 (9)| 00:00:07 |
| 1 | HASH GROUP BY | | 10 | 30 | 574 (9)| 00:00:07 |
| 2 | INDEX FAST FULL SCAN| TEST_INDEX | 1000K| 2929K| 532 (2)| 00:00:07 |
------------------------------------------------------------------------------------
9 rows selected.
SQL>
之所以如此重要,是因为在常规B-TREE索引中不包含NULL值,但是GROUP
BY必须在查询中将NULL包括为分组“值”。通过告诉优化器其中没有NULL,col
可以自由使用效率更高的索引(FTS使我花费了近3.55秒的时间)。这是元数据如何影响优化器的经典示例。
顺便说一下,这显然是10g或11g数据库,因为它使用HASH GROUP BY算法,而不是较旧的SORT(GROUP BY)算法。
问题内容: 我有一个表,其中列上有部分索引。 如果我执行简单查询,则使用索引: 但是如果我使用它进行查询,则不会使用索引: 为什么在第二种情况下不使用索引?有什么办法可以加快这个查询? (请注意,在此示例中,我已截断了数组,并测试了更多元素,但结果却相同,缓慢) 问题答案: 实际上,它 正在 使用索引。只是做不同的事情。 索引扫描一行一行地访问,以随机顺序从一个磁盘页面到下一个磁盘页面来回移动。
问题内容: 我有一张表,其中有一个名为的整数列。我在该列上有一个索引。 但是似乎Postgres不想使用我的索引: 知道为什么会这样吗? 问题答案: 因为: 您选择的行太多了,以至于读取整个表都比较便宜。
我得到的回答是。。。 {"错误":{"root_cause":[{"type":"illegal_argument_exception","原因":"畸形动作/元数据行[2],预期START_OBJECT或END_OBJECT找不到[VALUE_STRING]"}],"type":"illegal_argument_exception","原因":"畸形动作/元数据行[2],预期START_OBJ
问题内容: 为什么这段代码不抛出?它在不使用方法的情况下修改了一段时间,这是唯一安全的删除方法。 如果将替换为,则会得到相同的结果。但是,如果我将列表更改为或只是得到了预期的异常。到底是怎么回事?我正在使用是否相关。 编辑 我找到了以下链接 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078 相关部分是 天真的解决方案是将协同修改
问题内容: 我在ColdFusion代码中碰巧遇到了这些值,但Google计算器似乎有相同的“错误”,但差不为零。 416582.2850-411476.8100-5105.475 = -2.36468622461E-011 http://www.google.com/search?hl=zh_CN&rlz=1C1GGLS_enUS340US340&q=416582.2850+-+411476.8
问题内容: 我有2张表,如下所示: 当我解释查询时: postgres给我这个: 过了一会儿给我这个完全相同的查询(仍然不使用索引): 我的问题是:如果我仅按构成唯一索引的st值和类型值进行过滤,为什么不使用此唯一索引? 问题答案: 您的表没有足够的行来使用索引。它们适合放在单个磁盘页面中,因此使用cpu时间读取整个内容并筛选出行要比两次执行同一操作(一次用于索引,另一次用于数据)要快。