sql - IS FALSE 和 = 'f' 在 Postgres 和索引使用中的区别

标签 sql ruby-on-rails postgresql

在 Postgres 9.6 中,在具有大约 1200 万行的用户表中,active bool 列上有一个 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

但是,使用 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

绝大多数记录的事件值为 true,而且我知道索引并不总是更快。

Rails 似乎更喜欢 active = 'f' 语法,因为这是它在构建查询时输出的内容。

为什么这些不同?它们有何不同?应该使用另一个吗?

最佳答案

区别在于 NULL 值的处理方式。根据 docs :

  • IS FALSE 将始终返回 bool 值,即使参数为 null。
  • = 'f' 如果参数为 null,则返回 null。

为了说明,

rnubel=# SELECT NULL = 'f' as equals_false, NULL IS FALSE as is_false;

 equals_false | is_false
--------------+----------
              | f

通常,SQL 中的大多数事物都将在三元逻辑基础上运行,其中空值产生空结果;因此,Rails 默认使用与该基础一致的运算符也就不足为奇了。但是,它与您在 Ruby 中的预期不同(其中 !nil == true),因此它可能是许多意外行为的原因。

关于sql - IS FALSE 和 = 'f' 在 Postgres 和索引使用中的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46410610/

相关文章:

ruby-on-rails - 激活摘要未保存到数据库

sql - Postgresql 连接表而不丢失记录

ruby-on-rails - ruby on rails 中的自动测试错误

ruby-on-rails - 如何检查 token 是否已过期

sql - 仅当行不存在时才在 PL/pgSQL 中运行 SQL 语句

python - 如何使用 Django ORM 通过 DateTimeField() 计算 Postgresql 数据库中的项目

php - 从选择结果更新行

sql - 查看从存储过程创建的临时表

sql - 在 PostgreSQL 中选择没有函数的动态列

MySQL 检索组的最新记录