需要帮助优化MySQL查询-或连接中的语句导致查询时间过长

需要帮助优化MySQL查询-或连接中的语句导致查询时间过长,mysql,sql,performance,Mysql,Sql,Performance,我对数据执行此查询需要60-80秒以上的时间。查询中的一个更改将其降低到250ms以下,但此更改会导致排除所需的数据 这里有一个SQL转储(对于sqlfiddle来说太大了),它是我正在处理的查询的基本数据: 注意:我添加了“SQL\u NO\u CACHE”用于测试目的,我知道有些列名有拼写错误,但这些列名仅用于测试目的,转储中的模式是基于真实数据构建的,但不包括真实列名和数据 慢查询 查询 说明 差别 除去 OR `Table3`.`table1RecordID`=`Table1`.`rec

我对数据执行此查询需要60-80秒以上的时间。查询中的一个更改将其降低到250ms以下,但此更改会导致排除所需的数据

这里有一个SQL转储(对于sqlfiddle来说太大了),它是我正在处理的查询的基本数据:

注意:我添加了“SQL\u NO\u CACHE”用于测试目的,我知道有些列名有拼写错误,但这些列名仅用于测试目的,转储中的模式是基于真实数据构建的,但不包括真实列名和数据

慢查询 查询 说明 差别 除去

OR `Table3`.`table1RecordID`=`Table1`.`recordID`
从6号线开始

说明 +----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+ |id |选择|类型|类型|可能|键|键|列|参考|行|附加| +----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+ |1 |简单|表1 | ref | PRIMARY,groupName | groupName | 768 | const | 77 |使用where;使用指数;使用临时设备;使用文件排序| |1 |简单|表2 |参考| fk | U注册ID,fk | U packageID | fk | U packageID | 5 | testDb.Table1.recordID | 88 |使用where| |1 |简单|表3 | eq | ref | PRIMARY,regStatus | PRIMARY | 4 | testDb.Table2.tabel3RecordID | 1 |使用where| +----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+ 无法使用更快的查询的原因是,可能存在这样的情况,即Table3包含table1RecordID中的ID数据,以便与Table1的recordID匹配,因此我希望它包含在Table2的数据中。所以我想要表3中的数据,其中表2有一个匹配的ID,以及表3中表1 ID与表3中的列匹配的表3数据。当我在ON子句中使用OR来获取包含的数据时,这会大大降低查询速度。我发现问题在于它创建了一个临时表,并将其复制到文件系统(filesort)

我非常感谢任何关于如何获得所需数据并解决查询时间缓慢问题的反馈


感谢advanced。

尝试对表进行两次联接,并对每个联接分别进行比较。我认为这是逻辑:

SELECT SQL_NO_CACHE `Table1`.`recordID`
FROM `Table1`
      LEFT JOIN `Table2` ON `Table1`.`recordID`=`Table2`.`table1RecordID`
      LEFT JOIN `Table3` ON `Table2`.`tabel3RecordID`=`Table3`.`recordID`
      LEFT JOIN `Table3` t3 on t3.`table1RecordID`=`Table1`.`recordID`
WHERE (`Table3`.`status` in ('3', '4') or t3.status in ('3', '4'))  AND
      (`Table1`.`groupName` = 'Sample Name')
GROUP BY `Table2`.`tabel3RecordID` ASC, `Table1`.`recordID` ASC;

表3没有连接到表1-难怪它很慢!在tabl3.recordID上添加索引将这些查询分为两个查询,然后在JOIN子句中使用union而不是OR。2快速查询优于1复杂查询slow@suspectus我如何使用另一个连接,但仍然能够像现在一样将所有数据分组?@SamD我认为联合可能是一个诀窍,但我在编写它时遇到了困难。有没有人帮我写那笔钱?谢谢。是否有过这样的情况,表3会以两种方式连接(导致同一行连接两次-每个连接方法连接一次)这很快而且有效,但是当我想从表3中选择一个列时,使用两个单独的连接是行不通的。我知道示例中没有附加数据,但为了举例说明,假设有另一列存储了我要显示的字符串值,有两个连接,一些数据将位于
表3
中,一些数据将位于
表3
的别名
t3
@MasterEthan中。您可以使用
coalesce(table3.colx,t3.colx)
从其中一个表中获取值。@GordanLinoff忘记了这一点。让我再举一个例子,当我需要在表3的一列中加入更多的表时,会发生什么情况?@MasterEthan。您还需要在
t3
中包含条件。这就是我的想法。讨厌这个查询有多复杂。不知道是否最好取消Table3.table1RecordID,让它使用Table2存储所有相关数据,这将需要大量更改和迁移大量现有数据。
SELECT SQL_NO_CACHE
 `Table1`.`recordID`
FROM
  `Table1`
  LEFT JOIN `Table2` ON `Table1`.`recordID`=`Table2`.`table1RecordID`
  LEFT JOIN `Table3` ON `Table2`.`tabel3RecordID`=`Table3`.`recordID`
WHERE
  (`Table3`.`status` = '3' OR `Table3`.`status` = '4')  AND
  (`Table1`.`groupName` = 'Sample Name')
GROUP BY `Table2`.`tabel3RecordID` ASC, `Table1`.`recordID` ASC;
OR `Table3`.`table1RecordID`=`Table1`.`recordID`
+----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+ | id | select_type | table | type | possible_key | key | key_len | ref | rows | Extras | +----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+ | 1 | SIMPLE | Table1 | ref | PRIMARY,groupName | groupName | 768 | const | 77 | Using where; Using index; Using temporary; Using filesort | | 1 | SIMPLE | Table2 | ref | fk_registrationID,fk_packageID | fk_packageID | 5 | testDb.Table1.recordID | 88 | Using where | | 1 | SIMPLE | Table3 | eq_ref | PRIMARY,regStatus | PRIMARY | 4 | testDb.Table2.tabel3RecordID | 1 | Using where | +----+-------------+--------+--------+--------------------------------+--------------+---------+------------------------------+------+-----------------------------------------------------------+
SELECT SQL_NO_CACHE `Table1`.`recordID`
FROM `Table1`
      LEFT JOIN `Table2` ON `Table1`.`recordID`=`Table2`.`table1RecordID`
      LEFT JOIN `Table3` ON `Table2`.`tabel3RecordID`=`Table3`.`recordID`
      LEFT JOIN `Table3` t3 on t3.`table1RecordID`=`Table1`.`recordID`
WHERE (`Table3`.`status` in ('3', '4') or t3.status in ('3', '4'))  AND
      (`Table1`.`groupName` = 'Sample Name')
GROUP BY `Table2`.`tabel3RecordID` ASC, `Table1`.`recordID` ASC;