sql - 如何在 Postgres/Rails 中禁用 OR 条件优化

标签 sql ruby-on-rails postgresql

我有一个名为 A 的模型,其中包含列 colcol2col1 有一个唯一索引。 (我正在使用 Postgres 数据库。)

class A < ActiveRecord::Base
  # id, col1, col2
end

数据:

id  col1   col2
==  ====   ====
1   2       3
2   3       4

让我们尝试在 col2col1 中找到与给定值匹配的第一行。

a = A.first(:conditions=> ["col2 = :id OR col1 = :id", {:id => 3}])
# select * from A where (col2 = 3 OR col1 = 3) LIMIT 1

上面的 SQL 返回第 2 行而不是第 1 行。我怀疑查询优化器选择首先执行 col1 = 3,因为 col1 具有唯一索引。

如何覆盖此行为?我如何指示 Postgres 优化器将现有顺序用于 OR 条件?

最佳答案

如果您没有指定明确的顺序,那么第一行就没有任何意义;特定时刻特定查询的结果集当然会有第一行,但不能保证使用相同数据再次运行相同查询会产生相同的第一行。关系数据库中的表没有排序,因此根本没有指定的现有顺序。你在做一个错误的假设;该实现可能会隐式地按磁盘上的 PK 对记录进行排序,但不能保证这一点,也不能保证下一个版本的行为相同;此外,不能保证数据库将按磁盘顺序返回行,除非您使用 ORDER BY 子句指定了特定顺序,否则数据库可以自由地以任何方式对行进行排序。

如果你想要一个订单,那么你应该包含一个 ORDER BY 子句;你可能想要更像这样的东西:

a = A.where("col2 = :id OR col1 = :id", {:id => 3}).order(:id).first

如果你想在 col1 之前查看 col2 那么你应该这样说:

a =  A.where('col2 = :id', :id => 3).order(:id).first \
  || A.where('col1 = :id', :id => 3).order(:id).first

col2 = :id OR col1 = :idcol1 = :id OR col2 = :id 是等效的 bool 表达式,因此数据库可以自由检查 col2 = :idcol1 = :id 之前、之后或同时,它可以按照它喜欢的任何顺序自由访问行。

关于sql - 如何在 Postgres/Rails 中禁用 OR 条件优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8555920/

相关文章:

mysql - 如果左侧存在某些内容,则返回左侧表和右侧表中的所有结果

ruby-on-rails - 如何在 ruby​​ on rails 中使用友好 ID 从 URL 中删除模型名称

hibernate - 在 hibernate/jpa 环境中实际删除实体?

postgresql - 如何为窗口函数(postgresql)排序 "string_agg"中的字符串?

sql - 给定一组 ID,返回仅包含这些 ID 的订单子(monad)集

C# 在 SQL 中编辑行

sql - PostgreSQL upper function on the ascii 152 character ("ÿ")

sql - 如何从 SQL 表中删除相反的行

ruby-on-rails - group_by 之后的 ruby​​ on rails 求和字段

ruby-on-rails - Rails 3 模板 : strange beahaviour of inject_into_file