mysql - Rails/MySQL : Group/Distinct doubles query time using LEFT JOINS/slow performance

标签 mysql ruby-on-rails performance join

我有一个(有点)复杂的查询,返回 60K 多条客户记录。我有两个左外连接,需要与查询一起使用来搜索关联记录:

customers = customers.
  left_outer_joins(:phones, :emails).
  select("customers.id, customers.name, ...")

if params[:sSearch].present?
  params[:sSearch] = parse_phone_number(params[:sSearch])

  customers = customers.where(
    "customers.name like :search OR
    ..
    phones.number like :search OR
    emails.email like :search",
    search: "%#{params[:sSearch]}%"
  )
end

customers = customers.
  group('customers.id').
  order("#{sort_column} #{sort_direction}).
  page(page).
  per(per_page)

(注意:这在数据表 ajax 调用中使用,因此 sort_column、sort_direction、page 和 per_page 都是其参数。)

我的所有索引都已排好。

这是我面临的主要问题:如果我不使用 group('customers.id'),由于左外连接,它将返回重复的客户记录。但添加 group 子句似乎会使查询时间增加至少 2 倍。在查询末尾使用 .distinct 似乎比使用 group 还要慢一点。

是否有更好/更快的方法来不返回具有左外连接的重复项而不显着增加查询时间?目前这需要超过 1000 毫秒。

编辑:为了回答下面影子的评论 - 我正在加入多个电话/电子邮件,因为我需要搜索它们。我期望的是,如果客户记录与搜索匹配(假设在已连接的手机上),它只会返回一个客户 - 而不是两个。

最佳答案

如果您只想搜索地址/电话号码,但不想显示它们,请使用带有子查询的存在运算符而不是联接。

sql 中的代码如下所示:

select *
from customers c
where c.name like '%...%'
    or exists (select 1 from emails e where e.email like '%...%' and e.customer_id=c.id) ...

但是,如果您确实想显示地址和电话号码,则必须使用联接。在这种情况下,您可能需要使用 MySQL 的内置 group_concat() 函数将各种地址和电话号码连接成一个值。

其他需要考虑的事情:

  1. 使用union代替一系列or条件
  2. 尽可能尝试使用全文索引和搜索,而不是 like,因为 like '%...%' 过滤器无法使用索引来加速查询。

关于mysql - Rails/MySQL : Group/Distinct doubles query time using LEFT JOINS/slow performance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43762469/

相关文章:

ruby-on-rails - 如何根据使用Rails的Elastic搜索中的用户选择来提高特定搜索结果的排名

sql - PostgreSQL 中的慢 GroupAggregate

android - 在具有相同可绘制 ID 的 TextView 上调用 setBackground 两次。会发生什么?

javascript - 通过window.prompt将一些数据发布到mysql数据库的特定字段(代码运行不正常)

MySQL 使用另一个表的外键创建表 : errno:150 occurs.

ruby-on-rails - 升级到 OSX Lion 会影响我当前的 Rails 环境吗?

ruby-on-rails - 数字字段溢出 - 到底是哪个字段?

air - 为什么 adobe air 这么慢

php - 格式化 MySQL 记录的显示结果

php - MySQL 从查询结果中获取数据