我在 Postgres 9.1 数据库上运行了两个不同的 SQL 查询:
SELECT device_id, country FROM devices WHERE
(device_id = '97c179bd' AND country = 'US') OR
(device_id = 'bf5f50c6' AND country = 'US') OR
....
(device_id = '0e66c04d' AND country = 'US')
运行 12 秒(由 OR 分隔的 3620 个子句)
和
SELECT device_id, country FROM devices WHERE
(device_id = '97c179bd' AND country = 'US') OR
(device_id = 'bf5f50c6' AND country = 'US') OR
....
(device_id = '0e66c04d' AND country = 'US') OR
(device_id = '0e66c04d' AND country = 'different')
运行 0.6 秒(由 OR 分隔的 3620 个子句)
在第一个中,每个子句中的国家条件都是相同的。在第二个中,我在最后一个条款中将国家/地区切换为“不同”。
第一个 select 语句需要 12 秒运行,第二个 select 语句需要 0.6 秒运行。
在第一个查询中,CPU 在几乎所有 12 秒内都固定在 100%,而没有任何磁盘读取,这表明它很可能是解析器花费了这么长时间。第二个查询不会发生这种情况。
我已经运行了 EXPLAIN ANALYZE 并获得了关于如何分解两个查询的完全相同的结果。
这里发生了什么?为什么每个 WHERE 子句语句中的第二个条件相同会导致查询时间更长?
编辑:
来自第一个查询的 EXPLAIN ANALYZE 的前几行:
设备上的位图堆扫描(成本=18807.49..52584.74 行=3564 宽度=39)(实际时间=73.994..78.994 行=3620 循环=1)
重新检查条件: (((device_id = '97c179bd'::text) AND (country = 'US'::text)) OR ((device_id = 'bf5f50c6'::text) AND (country = 'US'::text) ) OR ((device_id = '3b05d35a'::text) AND (country = 'US'::text)) OR ((device_id = 'c6684bc0'::text) AND (country = 'US'::text)) 或((device_id = '0e66c04d'::text) AND (country = 'US'::text))
来自第二个查询的 EXPLAIN ANALYZE 的前几行:
设备上的位图堆扫描(成本=18806.59..85317.68 行=3563 宽度=39)(实际时间=74.737..79.769 行=3619 循环=1)
重新检查条件: (((device_id = '97c179bd'::text) AND (country = 'US'::text)) OR ((device_id = 'bf5f50c6'::text) AND (country = 'US'::text) ) OR ((device_id = '3b05d35a'::text) AND (country = 'US'::text)) OR ((device_id = 'c6684bc0'::text) AND (country = 'US'::text)) 或((device_id = '0e66c04d'::text) AND (country = 'US'::text))
编辑2:
以下是两个 EXPLAIN ANALYZE 结果: