我在“operator”字段上有一个300K行和b-tree索引的表。 虽然我运行此查询但它没有使用索引。 “operator”与dict.vw_dict_operator.id具有相同的数据类型。
EXPLAIN SELECT
id,
name
FROM
dict.vw_dict_operator self
WHERE
EXISTS (
SELECT 42 FROM ti.ti_flight_availability flight_avail
WHERE flight_avail.operator = self.id
)
ORDER BY
self.name
"Sort (cost=3349.66..3351.02 rows=545 width=18)"
" Sort Key: dict_operator.name"
" -> Seq Scan on dict_operator (cost=0.00..3324.89 rows=545 width=18)"
" Filter: ((NOT trash) AND (subplan))"
" SubPlan"
" -> Seq Scan on ti_flight_availability flight_avail (cost=0.00..8513.66 rows=3750 width=0)"
" Filter: (operator = $0)"
UPD:谢谢@gbn。连接表时也不使用索引
EXPLAIN SELECT self.id, self.name
FROM dict.vw_dict_operator self JOIN ti.ti_flight_availability flight_avail
ON flight_avail.operator = self.id
"Nested Loop (cost=0.00..92988.47 rows=228639 width=18)"
" -> Seq Scan on ti_flight_availability flight_avail (cost=0.00..7754.33 rows=303733 width=4)"
" -> Index Scan using pk_dict_operator on dict_operator (cost=0.00..0.27 rows=1 width=18)"
" Index Cond: (dict_operator.id = flight_avail.operator)"
" Filter: (NOT dict_operator.trash)"
答案 0 :(得分:2)
为什么不使用JOIN?你有分析吗?统计数据怎么样?检查此表的pg_stats以获取更多信息。 pg_class中的reltuples和relpup对于表及其索引也很有趣。
编辑: JOIN期望228639行。顺序扫描需要303733行,只有一小部分。当这些100k记录遍布整个地方时,数据库无论如何都必须扫描重新分页。顺序扫描将比索引扫描更快,顺序扫描(快速)序列读取,索引扫描将是两个(!)慢随机读取:来自索引的信息和来自索引的信息桌子。
如果您认为该计划有误,请对该表进行分析,并向我们展示pg_stats和pg_class中有关表和索引的信息。
ANALYZE;
SELECT relpage, reltuples WHERE relname = 'table_or_index_name';
SELECT * FROM pg_stats WHERE tablename = 'name of your table';
答案 1 :(得分:0)
如果您改为加入,它会使用索引吗?
答案 2 :(得分:0)
你对dict.vw_dict_operator有什么索引?
EXISTS是JOIN的一种形式(简单,我知道),并且可能会忽略索引,因为没有方便的JOIN。所以它会扫描。
编辑:
JOIN计划也没有在ti_flight_availability上使用索引......但是你声明你有一个索引吗?