tib*_*bon 5 sql postgresql ruby-on-rails
在Postgres 9.6中,在一个大约有1200万行的用户表上,active
布尔列上有一个btree索引.
EXPLAIN ANALYZE SELECT * FROM users WHERE active = 'f' LIMIT 1;
Limit (cost=0.00..0.14 rows=1 width=982) (actual time=0.039..0.040 rows=1 loops=1)
-> Seq Scan on users (cost=0.00..3190979.68 rows=23264168 width=982) (actual time=0.036..0.036 rows=1 loops=1)
Filter: (NOT active)
Rows Removed by Filter: 115
Planning time: 0.161 ms
Execution time: 0.067 ms
Run Code Online (Sandbox Code Playgroud)
但是,使用IS FALSE
似乎使用索引.
EXPLAIN ANALYZE SELECT * FROM users WHERE active IS FALSE LIMIT 1;
Limit (cost=0.44..0.59 rows=1 width=982) (actual time=0.054..0.056 rows=1 loops=1)
-> Index Scan using index_users_on_active on users (cost=0.44..2059.14 rows=13183 width=982) (actual time=0.051..0.051 rows=1 loops=1)
Index Cond: (active = false)
Filter: (active IS FALSE)
Planning time: 0.170 ms
Execution time: 0.094 ms
Run Code Online (Sandbox Code Playgroud)
绝大多数记录,活动值是true
,我理解索引并不总是更快.
似乎Rails更喜欢active = 'f'
语法,因为它是构建查询时输出的内容.
为什么这些不同?他们有什么不同?是否应该使用其他?
区别在于如何处理NULL值.根据文档:
IS FALSE
即使参数为null,也总会返回一个布尔值.= 'f'
如果参数为null,则返回null.所以说明一下,
rnubel=# SELECT NULL = 'f' as equals_false, NULL IS FALSE as is_false;
equals_false | is_false
--------------+----------
| f
Run Code Online (Sandbox Code Playgroud)
通常,SQL中的大多数东西都将在三元逻辑的基础上运行,其中空值产生空结果; 因此,Rails默认使用与该基础一致的运算符并不奇怪.但是,它与您在Ruby(在哪里!nil == true
)的期望不同,因此它可能是导致许多意外行为的原因.
归档时间: |
|
查看次数: |
1160 次 |
最近记录: |