And*_*ndy 4 postgresql performance optimization order-by query-performance
我在 Postgres 9.6 中有下表:
Table "public.TagNotifications"
Column | Type | Modifiers
--------------+-----------------------------+-----------------------------------------------------------------
createdAt | timestamp with time zone | not null default now()
updatedAt | timestamp with time zone | not null default now()
id | integer | not null default nextval('"TagNotifications_id_seq"'::regclass)
tag | character varying(255) | not null
triggerId | integer |
userId | integer | not null
comparison | "TagNotificationComparison" |
setpoint | double precision |
severity | "TagNotificationSeverity" |
acknowledged | boolean | not null default false
value | double precision |
Indexes:
"TagNotifications_pkey" PRIMARY KEY, btree (id)
"TagNotificactions_userId_acknowledged_createdAt_tag_id" btree ("userId", acknowledged, "createdAt" DESC, tag, id)
"TagNotificactions_userId_acknowledged_tag_createdAt_id" btree ("userId", acknowledged, tag, "createdAt" DESC, id)
Foreign-key constraints:
"TagNotifications_tag_fkey" FOREIGN KEY (tag) REFERENCES "Metadata"(tag) ON UPDATE CASCADE ON DELETE CASCADE
"TagNotifications_triggerId_fkey" FOREIGN KEY ("triggerId") REFERENCES "TagNotificationTriggers"(id) ON UPDATE CASCADE ON DELETE SET NULL
"TagNotifications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "Users"(id) ON UPDATE CASCADE ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)
我正在尝试确保以下查询(以及基于游标分页的类似查询)的良好性能:
EXPLAIN
SELECT * FROM "TagNotifications"
WHERE ("userId" = 2 AND "acknowledged" = false)
ORDER BY "tag" ASC, "createdAt" DESC, "id" ASC
LIMIT 6;
QUERY PLAN
------------------------------------------------------------------------------------
Limit (cost=840.10..840.12 rows=6 width=75)
-> Sort (cost=840.10..856.04 rows=6376 width=75)
Sort Key: tag, "createdAt" DESC, id
-> Seq Scan on "TagNotifications" (cost=0.00..725.81 rows=6376 width=75)
Filter: ((NOT acknowledged) AND ("userId" = 2))
(5 rows)
Run Code Online (Sandbox Code Playgroud)
为什么 Postgres 不够聪明,无法在这种情况下使用索引?如果我包含"userId"和acknowledgedin ORDER BY,它使用索引,但由于WHERE条件,这应该不是必需的:
EXPLAIN
SELECT * FROM "TagNotifications"
WHERE ("userId" = 2 AND "acknowledged" = false)
ORDER BY "userId" ASC, "acknowledged" ASC, "tag" ASC, "createdAt" DESC, "id" ASC
LIMIT 6;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.41..2.27 rows=6 width=75)
-> Index Scan using "TagNotificactions_userId_acknowledged_tag_createdAt_id" on "TagNotifications" (cost=0.41..1974.27 rows=6376 width=75)
Index Cond: (("userId" = 2) AND (acknowledged = false))
Filter: (NOT acknowledged)
(4 rows)
Run Code Online (Sandbox Code Playgroud)
它在 v10 中变得更加智能。
我认为它之前不够聪明的原因在这里描述:
https://www.postgresql.org/message-id/1788.1481605684@sss.pgh.pa.us
我不知道如何总结,所以我只会说“索引中的布尔值令人困惑”