我有两张桌子:
table1 (about 200000 records)
number varchar(8)
table2 (about 2000000 records)
number varchar(8)
两个表中的字段“数字”都有标准索引。 对于table1中的每条记录,table2中分配了大约10条记录。
我执行查询:
explain select table1.number from table1, table2 where table1.number = table2.number;
查询计划显示不会使用索引,Seq Scans遍布;)
但是,如果我将table1中的记录数量减少到~2000,则查询计划开始显示将使用该索引。
也许有人可以告诉我为什么postgresql以这种方式行事?
答案 0 :(得分:4)
顺序扫描对于选择性非常低的查询是正常的(也是最佳的) - 也就是说,对于遍历整个表的查询。
当你删除table1中的大多数行时,它不再覆盖table2中所有可能的不同值 - 这就是使用索引扫描的原因。
对于初学者,我建议您尝试此查询:
select * from pg_stats where tablename in ('table1','table2');
这是PostgreSQL用于构建查询计划的信息。
规划师本身非常复杂 - 请参阅文档(由Jonathan提及)和来源[http://doxygen.postgresql.org/ - > src / backend / optimizer]如果你好奇的话。
答案 1 :(得分:2)
是的,PostgreSQL docs可以告诉你!
以下是一些亮点:
当不使用索引时,它可以 用于测试以强制使用它们。 有运行时参数可以 关闭各种计划类型(见 第18.6.1节)。例如,转身 关闭顺序扫描(enable_seqscan) 和嵌套循环连接 (enable_nestloop),这是最多的 基本计划,将迫使系统 使用不同的计划。如果是系统 仍然选择顺序扫描或 嵌套循环连接然后有 可能是一个更根本的原因 索引没有被使用;对于 例如,查询条件没有 匹配索引。 (什么样的查询 可以使用什么样的索引 在前几节中解释过。)
如果强制索引使用确实使用了 索引,那么有两个 可能性:系统是 正确并且使用索引确实如此 不合适,或成本估算 查询计划没有反映出来 现实。所以你应该在查询时间 有和没有索引。解释 ANALYZE命令在这里很有用。
答案 2 :(得分:-1)
这可能取决于索引的创建方式。如果“number”实际上是一个数字,您应该考虑将列类型更改为bigint。同样,不是100%肯定,但我认为对字符列的索引与基于数字的字段的工作方式不同......但我可以说出我的屁股。