【问题标题】:How to optimize my MySQL query that takes more than 500 seconds如何优化耗时超过 500 秒的 MySQL 查询
【发布时间】:2023-02-14 09:59:20
【问题描述】:

这是我的 MySQL 查询,我使用了 LEFT JOIN:

SELECT ph.id, ph.number
FROM phone ph
LEFT JOIN linked_phones lp ON ph.number = lp.number
WHERE ph.userid = 10 and ph.active = 1 AND ph.linkid = 50 AND lp.number IS null

我想把所有没有关联的号码都选出来,但是执行时间太长了(500多秒)。 我在两个表上添加了索引:

  • 桌面电话的第一个索引:links idx(user id, active, linkedin )
  • 表 linked_phones 的第二个索引:number_idx(number)

这里有 EXPLAIN 查询的结果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ph ref links_idx links_idx 12 const,const,const 127935
1 SIMPLE al ALL name_idx,number_idx 84355 Range checked for each record (index map: 0xA); Not exists

当我仅从电话表执行第一部分时:

select count(1)
from phone 
where userid = 10 and active=1 AND linkid =50

它很快给出了结果:超过 84506 行

当我从另一个表执行第二部分时:

select count(1) from linked_phones where userid = 10

它也很快给了我结果:85149 行

我也尝试过使用子查询但同样的问题:

select id, number
from phone
where userid = 10 and active =1 AND linkid = 50
and number not in (select number from linked_phones where);

对于优化此查询的任何建议,我将不胜感激。

【问题讨论】:

  • 您能检查您的 2 个“数字”列的数据类型是否匹配吗?
  • 您的索引实际上看起来不错你为什么使用LIMIT而不使用ORDER BY
  • @Solarflare 是的,我检查发现电话表中的号码是bigint(25),但另一个表中的号码是char(64),问题是我无权更改这些列
  • @TimBiegeleisen 我刚刚添加了它来检查它是否有帮助并忘记删除它抱歉我更新了查询
  • 哦,我的我的。存储为数字数据类型的电话号码。那是残酷的数据设计。

标签: mysql query-optimization


【解决方案1】:

第一个查询将受益于

ph:  INDEX(userid, active, linkid, number,  id)
lp:  INDEX(number)

第二个使用NOT EXISTS 可能会运行得更快:

and  number not in (
        SELECT  number
            from  linked_phones where

-->

AND NOT EXISTS( SELECT 1 FROM linked_phones
                  WHERE number = phone.number )

(同样的索引适用。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2021-01-24
    相关资源
    最近更新 更多