我的查询执行时间差不多是8秒。我在查询上做了EXPLAIN
,但我不知道如何解释结果。有人可以帮我解决这个问题吗?以下是EXPLAIN
:
===============================================================================================================================================================================================
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
===============================================================================================================================================================================================
| 1 | PRIMARY | <derived2> | ALL | (NULL) | (NULL) | (NULL) | (NULL) | 669 | Using filesort |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2 | DERIVED | Workflow | const | PRIMARY | PRIMARY | 4 | | 1 | Using index |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2 | DERIVED | DataSource | ref | PRIMARY,WorkflowId | WorkflowId | 4 | | 1546 | Using where |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2 | DERIVED | ReadyLog | ALL | DataSourceId | (NULL) | (NULL) | (NULL) | 9463 | |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2 | DERIVED | DataSourceActivityLog | eq_ref | PRIMARY,DataSourceId | PRIMARY | 4 | func | 1 | Using where |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2 | DERIVED | User | eq_ref | PRIMARY | PRIMARY | 4 | my_db.DataSourceActivityLog.UserId | 1 | |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 3 | DEPENDENT SUBQUERY | DataSourceActivityLog | ref | DataSourceId | DataSourceId | 4 | my_db.DataSource.Id | 1135 | Using where; Using filesort |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
如果您需要我提供其他信息,请告知我们。感谢。
更新1:丑陋的查询:
SELECT WrappedData.*
FROM (SELECT DataSource.Id,
DataSourceActivityLog.Description,
DataSourceActivityLog.UserId,
DataSource.Status AS StatusCode,
( CASE
WHEN User.Name IS NULL THEN 'System'
ELSE User.Name
END ) AS `Username`,
ReadyLog.`Timestamp` AS `Received`,
DataSourceActivityLog.`Timestamp`
FROM DataSource
LEFT JOIN DataSourceActivityLog AS ReadyLog
ON ( ( ReadyLog.DataSourceId = DataSource.Id
AND ReadyLog.Description = 'ready' )
OR ( ReadyLog.DataSourceId = DataSource.RootId
AND ReadyLog.Description = 'ready' ) ),
DataSourceActivityLog
LEFT JOIN USER
ON USER.Id = DataSourceActivityLog.UserId,
Workflow
WHERE DataSource.Id IN ( 138, 139, 140, 141,
142, 143, 144, 145,
146, 147, 148, 149,
150, 151, 152, 153,
154, 155, 156, 157,
158, 160, 162, 163,
166, 167, 169, 170,
171, 173, 174, 176,
177, 179, 180, 182,
183, 185, 186, 187,
189, 190, 191, 193,
194, 196, 197, 199,
200, 201, 203, 204,
207, 208, 209, 211,
212, 214, 216, 217,
219, 221, 222, 223,
226, 227, 228, 231,
232, 233, 235, 237,
238, 242, 243, 240,
245, 246, 248, 250,
252, 253, 255, 256,
258, 259, 261, 263,
264, 266, 267, 271,
269, 272, 276, 274,
277, 280, 282, 284,
279, 287, 285, 288,
290, 291, 293, 298,
301, 299, 303, 304,
306, 309, 310, 311,
315, 316, 318, 322,
323, 325, 329, 330,
331, 336, 339, 343,
345, 346, 348, 351,
352, 354, 356, 357,
358, 360, 362, 364,
367, 369, 370, 373,
375, 376, 378, 381,
382, 384, 386, 388,
390, 391, 394, 395,
397, 400, 402, 404,
405, 408, 412, 413,
414, 415, 420, 421,
424, 425, 429, 430,
433, 434, 438, 439,
441, 442, 443, 445,
446, 447, 449, 451,
452, 453, 456, 457,
458, 459, 462, 464,
465, 466, 470, 473,
474, 475, 477, 478,
481, 482, 483, 485,
487, 488, 489, 491,
493, 494, 495, 497,
498, 500, 501, 502,
504, 505, 507, 508,
509, 512, 513, 514,
515, 516, 518, 519,
520, 521, 522, 524,
525, 526, 527, 529,
530, 531, 532, 534,
535, 536, 537, 539,
540, 541, 542, 544,
545, 546, 547, 549,
550, 551, 552, 553,
554, 556, 557, 559,
560, 561, 562, 564,
565, 566, 568, 569,
570, 571, 572, 574,
575, 576, 577, 579,
580, 581, 582, 583,
585, 586, 587, 588,
590, 591, 592, 593,
594, 596, 597, 598,
599, 601, 602, 603,
604, 606, 607, 608,
609, 611, 612, 613,
614, 616, 617, 618,
620, 621, 622, 623,
625, 626, 627, 628,
629, 631, 632, 633,
634, 636, 637, 638,
639, 641, 642, 643,
644, 646, 647, 648,
649, 651, 652, 653,
654, 656, 657, 658,
659, 660, 662, 663,
664, 665, 667, 668,
669, 670, 671, 673,
674, 675, 676, 678,
679, 680, 682, 683,
684, 686, 687, 688,
689, 691, 692, 693,
694, 697, 698, 699,
702, 703, 704, 707,
708, 709, 710, 712,
713, 714, 717, 718,
719, 720, 721, 724,
725, 726, 728, 729,
730, 734, 735, 736,
738, 739, 740, 742,
743, 744, 747, 748,
749, 751, 752, 753,
755, 756, 757, 759,
760, 761, 763, 764,
765, 767, 768, 769,
771, 772, 773, 775,
776, 777, 779, 780,
781, 782, 784, 785,
786, 788, 789, 790,
791, 793, 794, 795,
797, 798, 799, 800,
802, 803, 804, 807,
813, 814, 815, 816,
818, 822, 823, 824,
825, 830, 831, 832,
834, 835, 836, 837,
839, 840, 841, 842,
844, 845, 846, 848,
849, 850, 852, 853,
855, 856, 858, 859,
860, 862, 863, 864,
866, 867, 868, 870,
871, 872, 874, 875,
876, 877, 879, 880,
881, 883, 884, 886,
888, 889, 891, 892,
893, 895, 899, 900,
902, 903, 905, 906,
908, 909, 911, 912,
914, 915, 917, 918,
920, 921, 923, 925,
927, 929, 931, 932,
934, 936, 938, 940,
942, 944, 946, 948,
950, 952, 953, 955,
956, 958, 959, 961,
962, 963, 965, 966,
968, 969, 971, 972,
974, 975, 977, 978,
979, 981, 982, 983,
987, 988, 991, 992,
994, 995, 996, 998,
1000, 1001, 1002, 1003,
1005, 1007, 1008, 1009,
1011, 1013, 1014, 1016,
1017, 1019, 1020, 1022,
1023, 1024, 1025, 1028,
1029, 1032, 1033, 1035,
1036, 1038, 1040, 1041,
1043, 1045, 1046, 1049,
1050, 1052, 1053, 1055,
1056, 1059, 1060, 1063,
1064, 1067, 1068, 1070,
1071, 1073, 1074, 1076,
1077, 1079, 1080, 1082,
1083, 1087, 1088, 1090,
295, 296, 338, 1551,
1552, 1554, 1556, 1559,
1561, 1563, 1565, 1567,
1568, 1570, 1572, 1574,
1576, 1578, 1580, 1581,
1583, 1585, 1587, 1589,
1591, 1593, 1595, 1597,
1599, 1601, 1603, 1605,
1607, 1609, 1611, 1613,
1614, 1617, 1618, 1621,
1622, 1625, 1626, 1629,
1630, 1634, 1638, 1639,
1642, 1643, 1645, 1646,
1651, 1652, 1657, 1658,
1662, 1664, 1666, 1669,
1672, 1676, 1674, 1677,
1680, 1681, 1684, 1685,
1689, 1690, 1694, 1698,
1704, 1706, 1709, 1712, 1633 )
AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
FROM DataSourceActivityLog
WHERE DataSourceActivityLog.DataSourceId = DataSource.Id
AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
ORDER BY TIMESTAMP DESC
LIMIT 1)
AND ( DataSource.Status = '103' )
AND Workflow.Id = 14
AND DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
AND DataSource.`WorkflowId` = Workflow.`Id`
AND DataSource.IsDeleted = 0) AS WrappedData
ORDER BY WrappedData.`Timestamp` ASC
LIMIT 0, 1
答案 0 :(得分:5)
首先,这是一个很大的子查询似乎很奇怪。你为什么不能这样做:
SELECT DataSource.Id,
DataSourceActivityLog.Description,
DataSourceActivityLog.UserId,
DataSource.Status AS StatusCode,
( CASE
WHEN User.Name IS NULL THEN 'System'
ELSE User.Name
END ) AS `Username`,
ReadyLog.`Timestamp` AS `Received`,
DataSourceActivityLog.`Timestamp`
FROM DataSource
LEFT JOIN DataSourceActivityLog AS ReadyLog
ON ( ( ReadyLog.DataSourceId = DataSource.Id
AND ReadyLog.Description = 'ready' )
OR ( ReadyLog.DataSourceId = DataSource.RootId
AND ReadyLog.Description = 'ready' ) ),
DataSourceActivityLog
LEFT JOIN USER
ON USER.Id = DataSourceActivityLog.UserId,
Workflow
WHERE DataSource.Id IN (... )
AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
FROM DataSourceActivityLog
WHERE DataSourceActivityLog.DataSourceId = DataSource.Id
AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
ORDER BY TIMESTAMP DESC
LIMIT 1)
AND ( DataSource.Status = '103' )
AND Workflow.Id = 14
AND DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
AND DataSource.`WorkflowId` = Workflow.`Id`
AND DataSource.IsDeleted = 0
ORDER BY DataSourceActivityLog.`Timestamp` ASC
LIMIT 0, 1
我怀疑,但可能是错误的,导致WrappedData
导致ORDER BY效率低下,因为它无法使用任何索引,必须等待整个查询在排序之前完成。
接下来,似乎某些where子句应该像这样进入连接:
SELECT DataSource.Id,
DataSourceActivityLog.Description,
DataSourceActivityLog.UserId,
DataSource.Status AS StatusCode,
( CASE
WHEN User.Name IS NULL THEN 'System'
ELSE User.Name
END ) AS `Username`,
ReadyLog.`Timestamp` AS `Received`,
DataSourceActivityLog.`Timestamp`
FROM DataSource
LEFT JOIN DataSourceActivityLog AS ReadyLog
ON ( ( ReadyLog.DataSourceId = DataSource.Id
AND ReadyLog.Description = 'ready' )
OR ( ReadyLog.DataSourceId = DataSource.RootId
AND ReadyLog.Description = 'ready' ) ),
INNER JOIN DataSourceActivityLog ON DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
FROM DataSourceActivityLog
WHERE DataSourceActivityLog.DataSourceId = DataSource.Id
AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
ORDER BY TIMESTAMP DESC
LIMIT 1)
LEFT JOIN USER
ON USER.Id = DataSourceActivityLog.UserId
INNER JOIN Workflow ON DataSource.`WorkflowId` = Workflow.`Id`
WHERE DataSource.Id IN (... )
AND ( DataSource.Status = '103' )
AND Workflow.Id = 14
AND DataSource.IsDeleted = 0
ORDER BY DataSourceActivityLog.`Timestamp` ASC
LIMIT 0, 1
此外,别名DataSourceActivityLog AS ReadyLog
看起来好像返回了很多行。这应该是INNER JOIN
而不是LEFT JOIN
吗?根据你提供的内容很难分辨。
最后,DataSource.Id IN (... )
是如此之长,将这些ID放入查找表中可能会让您受益,您可以通过连接引用它们,而不是将它们全部输出到where子句中。
我知道这对EXPLAIN
没有帮助,但说实话,我认为在这种情况下你不会给你太多的帮助。
答案 1 :(得分:0)
我会尝试以下方法,首先将IN
子句的Id放在临时表(TempIds)中;如果您可以确定表Id=14
中存在Workflow
的记录,那么您可以删除INNER JOIN
到Workflow
表,并保留DataSource.WorkflowId = 14
的简单条件在WHERE
子句中;然后更改连接的顺序,以便首先评估INNER JOIN
,然后LEFT JOIN
;简化第一个LEFT JOIN
表达式并将不变条件ReadyLog.Description = 'ready'
移出OR
:
SELECT DataSource.Id,
DataSourceActivityLog.Description,
DataSourceActivityLog.UserId,
DataSource.Status AS StatusCode,
( CASE
WHEN User.Name IS NULL THEN 'System'
ELSE User.Name
END ) AS `Username`,
ReadyLog.`Timestamp` AS `Received`,
DataSourceActivityLog.`Timestamp`
FROM
TempIds INNER JOIN
DataSource ON TempIds.Id = DataSource.Id INNER JOIN
DataSourceActivityLog ON DataSourceActivityLog.DataSourceId = DataSource.Id
AND DataSourceActivityLog.Id = (
SELECT DataSourceActivityLog.Id
FROM DataSourceActivityLog
WHERE DataSourceActivityLog.Description = 'data_entry_ready'
AND DataSourceActivityLog.DataSourceId = DataSource.Id
ORDER BY TIMESTAMP DESC
LIMIT 1) LEFT JOIN
DataSourceActivityLog AS ReadyLog ON ReadyLog.Description = 'ready'
AND (ReadyLog.DataSourceId = DataSource.Id
OR ReadyLog.DataSourceId = DataSource.RootId) LEFT JOIN
USER ON USER.Id = DataSourceActivityLog.UserId
WHERE
DataSource.Status = '103'
AND DataSource.WorkflowId = 14
AND DataSource.IsDeleted = 0
ORDER BY DataSourceActivityLog.`Timestamp` ASC
LIMIT 0, 1;
最后,您应该考虑将以下索引添加到DataSourceActivityLog
表:
(Description ASC, DataSourceId ASC)