我正在开发一个使用 Postgres 作为其后备数据库的应用程序。我正在研究一个在数据库上执行SELECT
查询的组件,使用UI上的多选输入控件来提供查询的输入值。以前,此输入控件是传统的选择控件,因此一次只能指定一个选项。这意味着SQL查询看起来像这样:
SELECT * FROM items WHERE code = 'value1';
实现多选后,SQL查询将如下所示:
SELECT * FROM items WHERE code IN ('value1', 'value2', 'value3');
但是,我有一个问题,即用户何时只在多选中指定单个值。这意味着在括号中只指定了一个值:
SELECT * FROM items WHERE code IN ('value1');
我认识到这个查询在语义上与使用WHERE ... = ...
的查询相同。我的问题是两者之间是否存在显着的性能差异。我考虑过添加应用程序逻辑,如果只指定了一个值,那么选择是否用WHERE ... IN (...)
语句替换WHERE ... = ...
语句?这种优化是否必要?事实上,如果两种情况下的表现确实相同,那么当WHERE ... = ...
更灵活时,为什么还要使用WHERE ... IN (...)
呢?我对微优化过于担心吗?
谢谢。
答案 0 :(得分:2)
SELECT * FROM items WHERE code = ('value1');
(单一值)
的处理方式与
相同 SELECT * FROM items WHERE code = 'value1';
,
或SELECT * FROM items WHERE code IN ('value1');
。
所以性能没有区别。使用explain
进行检查。
答案 1 :(得分:2)
TLDR:它没有任何区别,性能总是相同的,因此IN
显然是您用例的胜利者。
可以进行快速测试来验证这一点:
test=# CREATE table test_in (id serial primary key);
CREATE TABLE
test=# explain select * from test_in where id = '1';
QUERY PLAN
---------------------------------------------------------------------------------
Index Only Scan using test_in_pkey on test_in (cost=0.15..2.17 rows=1 width=4)
Index Cond: (id = 1)
(2 rows)
test=# explain select * from test_in where id in ('1');
QUERY PLAN
---------------------------------------------------------------------------------
Index Only Scan using test_in_pkey on test_in (cost=0.15..2.17 rows=1 width=4)
Index Cond: (id = 1)
(2 rows)
请注意,计划是相同的,索引条件也是如此,这可以确保相同的成本不仅仅是偶然的。在执行的查询重写阶段,PostgreSQL检测到一些简单的等价情况,并以规范形式重写它们。
要查看另一个仍然在语义上等效的查询示例,但不会将其重写为您可以尝试的完全相同的计划:
test=# explain select * from test_in where id in ('1', '1');
QUERY PLAN
---------------------------------------------------------------------------------
Index Only Scan using test_in_pkey on test_in (cost=0.15..3.34 rows=2 width=4)
Index Cond: (id = ANY ('{1,1}'::integer[]))
(2 rows)