als*_*ste 8 sql postgresql indexing
我有一个带有索引的单词表(language_id,state).以下是EXPLAIN ANALYZE的结果:
没有限制
explain analyze SELECT "words".* FROM "words" WHERE (words.language_id = 27) AND (state IS NULL);
Bitmap Heap Scan on words (cost=10800.38..134324.10 rows=441257 width=96) (actual time=233.257..416.026 rows=540556 loops=1)
Recheck Cond: ((language_id = 27) AND (state IS NULL))
-> Bitmap Index Scan on ls (cost=0.00..10690.07 rows=441257 width=0) (actual time=230.849..230.849 rows=540556 loops=1)
Index Cond: ((language_id = 27) AND (state IS NULL))
Total runtime: 460.277 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)
限制100
explain analyze SELECT "words".* FROM "words" WHERE (words.language_id = 27) AND (state IS NULL) LIMIT 100;
Limit (cost=0.00..51.66 rows=100 width=96) (actual time=0.081..0.184 rows=100 loops=1)
-> Seq Scan on words (cost=0.00..227935.59 rows=441257 width=96) (actual time=0.080..0.160 rows=100 loops=1)
Filter: ((state IS NULL) AND (language_id = 27))
Total runtime: 0.240 ms
(4 rows)
Run Code Online (Sandbox Code Playgroud)
为什么会这样?如何在所有情况下使用索引?
谢谢.
我认为PostreSQL查询规划器只是认为在第二种情况下 - 具有LIMIT的情况 - 因为它[LIMIT]太小而不值得应用索引.所以这不是问题.
查看有关使用EXPLAIN和查询计划的PostgreSQL文档.在这种LIMIT 100
情况下,查询计划程序更喜欢对索引扫描进行顺序扫描的原因仅仅是因为顺序扫描更便宜.
ORDER BY
查询中没有子句,因此规划器可以使用与过滤条件匹配的前100个(随机)行.索引扫描需要首先读取索引页,然后读取数据页以获取相应的行.顺序扫描只需读取数据页面即可获取行.在您的情况下,表统计信息似乎表明有足够的(随机)行匹配过滤条件.获取100行的顺序页面读取的成本被认为比首先读取索引的成本便宜,然后获取实际的行.当您提高限制或较少的行与过滤条件匹配时,您可能会看到不同的计划.
使用默认设置规划者认为读随机页面(成本random_page_cost)读取顺序页(四倍的成本seq_page_cost).可以调整这些设置以调整查询计划(例如,当整个数据库在RAM中时,随机页面读取并不比顺序页面读取更昂贵,并且应该首选索引扫描).您还可以通过启用/禁用某些类型的扫描来尝试不同的查询计划,例如:
set enable_seqscan = [on | off]
set enable_indexscan = [on | off]
Run Code Online (Sandbox Code Playgroud)
虽然可以在全局范围内启用/禁用某些类型的扫描,但这应该仅用于每个会话的调试或故障排除.
VACUUM ANALYZE words
在测试查询计划之前也要运行,否则测试之间运行的自动真空(autovaccum)可能会影响结果.
归档时间: |
|
查看次数: |
3221 次 |
最近记录: |