【问题标题】:MySQL left join query too slowMySQL左连接查询太慢
【发布时间】:2014-11-26 20:08:29
【问题描述】:

我正在使用此 SQL 查询来连接两个表,即使限制为 10 也需要 10 秒。我检查了表是否已编入索引,所以我没有想法。任何帮助将不胜感激。

SELECT * FROM client_registration_request
LEFT JOIN customers ON (client_registration_request.customer_reference=customers.reference) 
LEFT JOIN region_info ON ( customers.country = region_info.id ) 
WHERE client_registration_request.client = 23
LIMIT 10

这是解释选择的结果

client_registration_request 索引

客户索引

和 region_info 索引

【问题讨论】:

  • 运行 explain select ... 并在此处添加输出以及您创建的索引
  • 尝试使用explain 查询并将结果发布到问题中。
  • 请看我更新的答案。
  • 如果它们不需要像 varchar 在两个表中将它们更改为 int 并且如果它需要是 varchar 在两个表中使它们相同并在删除之前的索引后删除索引这两列的索引。
  • 请注意,在没有 ORDER BY 子句的情况下,LIMIT 子句(相当)没有意义。

标签: mysql sql


【解决方案1】:

始终确保您用于 JOIN 的字段 - 条件已编入索引:

ALTER TABLE `client_registration_request` ADD INDEX `customer_reference` (`customer_reference`);
ALTER TABLE `customers` ADD INDEX `reference` (`reference`);

..等等。

更新:您的 EXPLAIN 表明您的索引键 customers 表未使用。所以尝试重新索引它们:

ALTER TABLE `customers` ADD INDEX `reference` (`reference`);
ALTER TABLE `customers` ADD INDEX `country` (`country`);

【讨论】:

  • 我通过尝试ALTER TABLE customers` ADD INDEX reference (reference) 得到#1061 - Duplicate key name 'reference';`
  • @phcm 然后取另一个名字:例如ALTER TABLE customers ADD INDEX reference (reference2);
  • 仍然很慢。 @Juancho Ramone 的回答使查询速度更快。需要 5 秒;更好,但仍然很慢。
  • @phcm 那么推广这个答案吧!
【解决方案2】:

您编写查询的方式是在执行两个左连接后限制和过滤结果,这就是为什么查询需要相同的时间。

为了使其更快,您需要尽快对其进行限制和过滤,在您的情况下,您希望在任何加入之前对其进行限制和过滤。

当您使用 LEFT JOINS 时,您可以限制和过滤第一个表并仍然获得相同的结果。试试这个:

SELECT * FROM 
(SELECT * FROM client_registration_request WHERE client_registration_request.client = 23 LIMIT 10) client_registration_request_TMP
LEFT JOIN customers ON (client_registration_request_TMP.customer_reference=customers.reference) 
LEFT JOIN region_info ON ( customers.country = region_info.id )

【讨论】:

  • 只是他的customers 表上没有索引,恕我直言。
  • Customers 表在引用字段(即连接中使用的字段)上有一个索引,只是查询没有使用该索引。
【解决方案3】:

这是您的查询,使用表别名(所以我觉得更容易理解):

SELECT *
FROM client_registration_request crr LEFT JOIN
     customers c
     ON crr.customer_reference = c.reference LEFT JOIN
     region_info r
     ON c.country = r.id
WHERE crr.client = 23
LIMIT 10

最重要的索引在client_registration_request(client) 上。但是,我会在其中包含其他 join 列。所以,第一个索引是client_registration_request(client, reference, country)。您可以将其创建为:

create index idx_client_registration_request_3 on client_registration_request(client, reference, country);

我假设其他表中的键已经是主键或索引。如果没有,您也应该在它们上建立索引customer(reference)region_info(country)

使用LIMIT 而不使用ORDER BY 是可疑的。当您运行查询时,您将获得一组任意匹配的行——您不能保证两次运行将返回相同的集合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 2015-02-22
    • 2015-11-02
    相关资源
    最近更新 更多