我有一个看起来像这样的rails查询:
Person.limit(10).unclaimed_people({})
def unclaimed_people(opts)
sub_query = where.not(name_id: nil)
if opts[:q].present?
query_with_email_or_name(sub_query, opts)
else
sub_query.group([:name_id, :effective_name])
.reorder('MIN(COALESCE(kudo_position,999999999)), lower(effective_name)')
.select(:name_id)
end
end
转换为SQL,查询如下所示:
SELECT "people"."name_id" FROM "people"
WHERE ("people"."name_id" IS NOT NULL)
GROUP BY "people"."name_id", "people"."effective_name"
ORDER BY MIN(COALESCE(kudo_position,999999999)), lower(effective_name) LIMIT 10
现在,当我在SQL查询上运行EXPLAIN
时,返回的内容表明我没有运行索引扫描。这是EXPLAIN
:
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=728151.18..728151.21 rows=10 width=53) (actual time=6333.027..6333.028 rows=10 loops=1)
-> Sort (cost=728151.18..729171.83 rows=408258 width=53) (actual time=6333.024..6333.024 rows=10 loops=1)
Sort Key: (min(COALESCE(kudo_position, 999999999))), (lower(effective_name))
Sort Method: top-N heapsort Memory: 25kB
-> GroupAggregate (cost=676646.88..719328.87 rows=408258 width=53) (actual time=4077.902..6169.151 rows=946982 loops=1)
Group Key: name_id, effective_name
-> Sort (cost=676646.88..686041.57 rows=3757877 width=21) (actual time=4077.846..5106.606 rows=3765261 loops=1)
Sort Key: name_id, effective_name
Sort Method: external merge Disk: 107808kB
-> Seq Scan on people (cost=0.00..112125.78 rows=3757877 width=21) (actual time=0.035..939.682 rows=3765261 loops=1)
Filter: (name_id IS NOT NULL)
Rows Removed by Filter: 317644
Planning time: 0.130 ms
Execution time: 6346.994 ms
注意查询计划的底部。有一个Seq Scan on people
。这不是我所期望的,在我的开发和生产数据库中,我在外部name_id
字段上放置了一个索引。以下是people
表的证据。
"index_people_name_id" btree (name_id) WHERE name_id IS NOT NULL
所以我的问题是为什么它不会运行索引。它可能来自ORDER BY
条款。我读到它可能会影响索引的执行。这是我从中读取它的网页。 Why isn't my index being used?
特别是这里是页面的引用。
索引通常不用于ORDER BY或执行连接。顺序扫描后跟显式排序通常比大表的索引扫描更快。但是,LIMIT与ORDER BY相结合通常会使用索引,因为只返回表的一小部分。
从查询中可以看出,我使用ORDER BY
与LIMIT
结合使用,所以我希望能够使用索引。这会过时吗? ORDER BY
真的会影响查询吗?为了让索引工作,我错过了什么?我并不是特别熟悉PGSQL的内部,所以任何帮助都会受到赞赏。