Tai*_*air 7 postgresql coalesce null-coalescing
我在Postgresql中有这个表:
CREATE TABLE my_table
(
id bigint NOT NULL,
value bigint,
CONSTRAINT my_table_pkey PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
my_table中有大约50000行.
问题是,为什么查询:
SELECT * FROM my_table WHERE id = COALESCE(null, id) and value = ?
Run Code Online (Sandbox Code Playgroud)
比这个慢:
SELECT * FROM my_table WHERE value = ?
Run Code Online (Sandbox Code Playgroud)
除了在app-layer中优化查询字符串之外,还有其他解决方案吗?
编辑:实际上,问题是如何重写查询select * from my_table where id=coalesce(?, id) and value=?以使最坏情况下的性能不低于select * from my_table where value=?Postgresql 9.0中的情况
从创建类似的表、填充它、更新统计信息,到最后查看 的输出EXPLAIN ANALYZE,我看到的唯一区别是第一个查询过滤器如下所示:
Filter: ((id = COALESCE(id)) AND (value = 3))
Run Code Online (Sandbox Code Playgroud)
第二个过滤器如下所示:
Filter: (value = 3)
Run Code Online (Sandbox Code Playgroud)
当“值”列上有索引时,我发现性能和执行计划有很大不同。在第一种情况下
Bitmap Heap Scan on my_table (cost=19.52..552.60 rows=5 width=16) (actual time=19.311..20.679 rows=1000 loops=1)
Recheck Cond: (value = 3)
Filter: (id = COALESCE(id))
-> Bitmap Index Scan on t2 (cost=0.00..19.52 rows=968 width=0) (actual time=19.260..19.260 rows=1000 loops=1)
Index Cond: (value = 3)
Total runtime: 22.138 ms
Run Code Online (Sandbox Code Playgroud)
在第二个
Bitmap Heap Scan on my_table (cost=19.76..550.42 rows=968 width=16) (actual time=0.302..1.293 rows=1000 loops=1)
Recheck Cond: (value = 3)
-> Bitmap Index Scan on t2 (cost=0.00..19.52 rows=968 width=0) (actual time=0.276..0.276 rows=1000 loops=1)
Index Cond: (value = 3)
Total runtime: 2.174 ms
Run Code Online (Sandbox Code Playgroud)
所以我想说它比较慢,因为数据库引擎 a) 评估 COALESCE() 表达式而不是对其进行优化,b) 评估它涉及额外的过滤条件。
尝试重写表单的查询
SELECT *
FROM my_table
WHERE value = ?
AND (? IS NULL OR id = ?)
Run Code Online (Sandbox Code Playgroud)
从我自己的快速测试
INSERT INTO my_table select generate_series(1,50000),1;
UPDATE my_table SET value = id%17;
CREATE INDEX val_idx ON my_table(value);
VACUUM ANALYZE my_table;
\set idval 17
\set pval 0
explain analyze
SELECT *
FROM my_table
WHERE value = :pval
AND (:idval IS NULL OR id = :idval);
Index Scan using my_table_pkey on my_table (cost=0.00..8.29 rows=1 width=16) (actual time=0.034..0.035 rows=1 loops=1)
Index Cond: (id = 17)
Filter: (value = 0)
Total runtime: 0.064 ms
\set idval null
explain analyze
SELECT *
FROM my_table
WHERE value = :pval
AND (:idval IS NULL OR id = :idval);
Bitmap Heap Scan on my_table (cost=58.59..635.62 rows=2882 width=16) (actual time=0.373..1.594 rows=2941 loops=1)
Recheck Cond: (value = 0)
-> Bitmap Index Scan on validx (cost=0.00..57.87 rows=2882 width=0) (actual time=0.324..0.324 rows=2941 loops=1)
Index Cond: (value = 0)
Total runtime: 1.811 ms
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8294 次 |
| 最近记录: |