【发布时间】:2015-07-31 19:18:01
【问题描述】:
我有这个查询(在 postgresql 中):
SELECT "table_1".* FROM "table_1"
INNER JOIN "join_table"
ON "table_1"."id" = "join_table"."table_1_id"
WHERE "join_table"."table_2_id" = 650727
ORDER BY table_1.created_at DESC
LIMIT 1
返回 1 个结果,但执行时间约为 250-300 毫秒
在table_1.created_at,还有join_table.table_1_id和join_table.table_2_id上有btree索引
当我只从查询中删除 LIMIT 1 时,执行时间下降到 ~13 毫秒。此特定查询当前仅返回一个结果(没有 LIMIT),但在 WHERE 中还有其他具有不同值的结果可能返回更多(这就是需要 LIMIT 的原因)。
为什么向已经只返回单个结果的查询添加 LIMIT 会大大增加执行时间?
这是LIMIT 1 的解释计划(这些对我来说总是很难完全理解...):http://explain.depesz.com/s/rOy
这里是没有 LIMIT 1 的解释计划:http://explain.depesz.com/s/q3d7
此外,如果我保留LIMIT 1,但将顺序更改为ASC,则查询也会下降到 13 毫秒。如果我将LIMIT 更改为LIMIT 20(但保留ORDER BY DESC)只需要22ms...wtf!?
所以它与ORDER BY DESC和LIMIT 1的组合有关(正好1)
【问题讨论】:
-
听起来你可能在你排序的列上有索引,因此当你的订单与索引匹配时它很快,当它与索引相反时它必须在它之前的内存中排序能够呈现结果。你能列出你的表上有哪些索引吗?
-
您是否尝试查看在 stackoverflow 上对 postgres 有限制的查询的其他性能问题?有很多主题,也许这些有帮助。
-
您是否有 3 个索引或 2 个索引,其中一个“复合索引”包含“join_table.table_1_id”以及“join_table.table_2_id”?使用复合索引,连接过滤可以完全由该索引处理。例如:在join_table(table_2_id,table_1_id)上创建索引join_table_ix1;
标签: sql postgresql query-optimization sql-execution-plan