【问题标题】:Adding index slows query添加索引会降低查询速度
【发布时间】:2019-03-11 13:30:34
【问题描述】:

我正在尝试优化查询

SELECT count(DISTINCT booking.id)
FROM ride 
       LEFT JOIN spot s1_ ON ride.from_spot_id = s1_.id
       LEFT JOIN spot s2_ ON ride.to_spot_id = s2_.id
       LEFT JOIN booking ON ride.booking_id = booking.id
       LEFT JOIN contact ON booking.contact_id = contact.id
WHERE (contact.first_name LIKE UPPER('%GAE%') OR contact.last_name LIKE UPPER('%GAE%') OR contact.email LIKE UPPER('%GAE%'))
  AND booking.paid_at IS NOT NULL
  AND booking.cancelled_at IS NULL;

查询在 2 秒左右执行。我在 booking.cancelled_at 上添加了一个索引

alter table booking add index booking_cancelled_at (cancelled_at);

现在大约需要 15 秒!

我去寻找,发现我可能想在 cancelled_at 和paid_at 上添加一个复合索引。我试过了,但 MYSQL 仍在选择 cancelled_at 索引。然后我尝试删除 cancelled_at 索引以强制使用复合索引。我当时还在 15 多岁左右。

结论是:没有索引2s,有索引(单个或复合)15s。

我查看了计划:

带索引

无索引

我不确定为什么完全扫描比使用索引更快?

任何有关如何解决此问题的指导或指示将不胜感激!

谢谢,

【问题讨论】:

  • 您确定您已经发布了来自两个不同查询的 EXPLAIN 计划吗?它们看起来一模一样。
  • 我真的不明白为什么这些是外连接!?!或者,事实上,为什么点会出现在查询中!?
  • 另外,您确定您使用的是区分大小写的排序规则吗?
  • 什么是表 c4_???
  • 如果您不需要LEFT,请不要使用它。这里似乎没有必要。

标签: mysql indexing


【解决方案1】:

对于给定的列,您只需要检查它是否为null,我看不出索引它的意义。相反,由于booking.paid_at 不能是null,我会将joinbookingcontact 修改为inner join,并使用booking.paidbooking.cancelled_at 中的条件在 on 标准中。

例子:

SELECT count(DISTINCT booking.id)
FROM ride 
       JOIN booking ON ride.booking_id = booking.id
       AND booking.paid_at IS NOT NULL
       AND booking.cancelled_at IS NULL
       JOIN contact ON ON booking.contact_id = contact.id
       AND (contact.first_name LIKE UPPER('%GAE%') OR contact.last_name LIKE UPPER('%GAE%') OR contact.email LIKE UPPER('%GAE%'))
       LEFT JOIN spot s1_ ON ride.from_spot_id = s1_.id
       LEFT JOIN spot s2_ ON ride.to_spot_id = s2_.id;

如果仍然很慢,您可以在查询前预选contact id 并使用 in 运算符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-06
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多