【问题标题】:Making a Limit X,Y MySQL Query with Joins Run Faster使用连接进行限制 X,Y MySQL 查询运行得更快
【发布时间】:2016-03-06 21:14:30
【问题描述】:

我有一个具有特定结构的 MySQL 查询,我想重写它以使其运行得更快。它目前运行速度非常慢,大约需要 255 秒才能执行。如果我删除加入,它会在

我怀疑该查询花费了很长时间,因为它不仅对找到的前 100 行进行了联接。这是真的吗,如果是这样,有没有办法在从主表中获取行后重写查询以进行连接?

数据来自一个“主”表 A,它有一个日期时间字段 (START_TIME) 和几个带有字符串值的表的外键(表、B、C、D)。

表 A 有 250 万行。表 B 有 600K 行。 表 A 在 START_TIME 有一个索引。表 B 在其 ID 值上有一个索引。

这是查询的基本形式。我不想对 START_TIME 设置上限,因为我总是想从查询中取回 100 条记录。我使用少于 100 条记录的响应来表明数据库中没有更多记录。

SELECT 
    A.START_TIME, A.F1, A.F2, B.STRING
FROM 
    A
     INNER JOIN B ON A.B_ID = B.ID
WHERE
    A.START_TIME >= '2015-03-22 05:23:44'
LIMIT 0, 100;

这是解释。对不起格式:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, SIMPLE, B, index, PRIMARY, FSN, 95, , 1, Using index; Using temporary; Using filesort
1, SIMPLE, A, ref, A_ix_B_ID,A_ix_C, A_ix_B_ID, 4, ag100_a$$burnaby.B.ID, 2, Using where

【问题讨论】:

  • 您可以使用ctrl-k将文本格式化为代码。
  • 现在你必须尝试每次添加一个表importblogkit.com/2015/05/how-do-you-eat-an-elephant你应该尝试每个选择都输入index
  • 这是一次添加一个表的结果: 仅表 A:8.7 秒,表 A 和 B:255 秒。问题仍然存在,我最初的问题仍然存在:有没有办法重组此查询,以便在从表 A 检索记录后完成连接。了解这一点非常重要,因为这是一个非常常见的查询。
  • 所以你说的时间是秒并期望我们给你一个解决方案?没有计划?给我们详细信息。 A中有多少行,B中有多少行。有多少A匹配A.START_TIME >= '2015-03-22 05:23:44' How many A.ID`匹配B.ID
  • 根据您对 A 和 B 中的行数的问题,该信息出现在我的帖子中,并且一直在我的帖子中。

标签: mysql database join query-optimization


【解决方案1】:

您必须提供解释计划,以便我们更好地帮助您。

https://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html

但是对于您的描述,您仍然需要索引。

START_TIME 旁边的 TableA 需要每个连接字段 B_id, C_id and D_id 的索引,也许对所有 4 个变量使用复合索引会更好

 CREATE INDEX A_Bid_idx ON A (B_id);
 CREATE INDEX A_Cid_idx ON A (C_id);
 CREATE INDEX A_Did_idx ON A (D_id);

 OR

 CREATE INDEX A_Full_idx ON A (B_id,C_id, D_id, START_TIME);

表 C 和 D 还需要 C.ID and D.ID 的索引。如果他们使用复合索引会更好

  (C.ID, C.STRING)  and
  (D.ID, D.STRING)

  CREATE INDEX C_id_idx ON C (ID);
  CREATE INDEX D_id_idx ON D (ID);

  OR

  CREATE INDEX C_id_string_idx ON C (ID, STRING);
  CREATE INDEX D_id_string_idx ON C (ID, STRING);

这样 db 不必进行查找来查找与 ID 关联的字符串值

【讨论】:

  • 关于更好的解释,您还想知道什么?但是 ist the biggest time savings found by doing to the joins AFTER the 100 records are found? Ill 添加您在上面建议的索引并重试。
  • 正如我所说,您仍然需要一些索引。你必须向我们展示解释计划,看看问题出在哪里use-the-index-luke.com/sql/explain-plan/mysql/…
  • 请帮帮我。我不知道还有什么信息可以告诉你。
  • 平均而言,任何 B_ID 值在表 A 中仅出现 4 次。我认为将其放入复合索引中不会有帮助。记住表 B 有 600K 行。
  • 阅读我给你的链接。这将向您展示 EXPLAIN <query> 的工作原理
【解决方案2】:
SELECT  A.START_TIME, A.F1, A.F2, 
      ( SELECT  STRING
            FROM  B
            WHERE  A.B_ID = B.ID 
      ) AS String
    FROM  A
    WHERE  A.START_TIME >= '2015-03-22 05:23:44'
    ORDER BY START_TIME
    LIMIT  0, 100; 

可能会跑得更快。从A 中“强制”使用INDEX(START_TIME)

请为两张表提供SHOW CREATE TABLE;我想检查数据类型等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 2021-11-11
    • 2014-11-29
    相关资源
    最近更新 更多