我使用了优秀的续集ORM,并且在某些时候我生成了一系列ID,并且我试图检索具有这些ID的用户。 e.g。
user_ids = [1, 2, 3]
User.where(id: user_ids).all
# (0.004223s) SELECT * FROM "users" WHERE ("id" IN (1, 2, 3))
但有时,用户列表是空的,我实际得到的是:
User.where(id: []).all
# (0.421287s) SELECT * FROM "users" WHERE ("id" != "id")
结果是正确的(即没有返回行),但查询慢了两个数量级。
在包含数百万行的表中,可能需要几秒钟才能返回。
我很好奇为什么这个查询首先生成,但我也很好奇为什么Postgres查询规划器似乎没有检测到这个矛盾并立即返回一个空数据集。 / p>
对此有一个简洁的解决方案,还是我必须检查所有阵列是否空虚?
我使用Ruby 2.0.0,Sequel 4.24.0& Postgres 9.3.6。
答案 0 :(得分:2)
有关此行为的closed issue on github。
我同意jeremyevans没有必要修复,因为很明显,研究结果将永远是空的。此外,你会认为PostgreSQL应该足够聪明,可以优化这样的查询,不应该进行全表扫描。
因此,在代码中修复此行为以避免完全调用数据库更有意义恕我直言:
user_ids.present? ? User.where(id: user_ids) : []
答案 1 :(得分:1)
请注意,续集的默认行为在4.25.0中已更改,因此此类查询将使用false
而不是id != id
。虽然id != id
在NULL处理方面可能更正确,但false
的性能优势使其成为更好的默认值。