我花了很多时间来优化这个查询,但它开始因较大的表而变慢。我想这些可能是最糟糕的问题类型,但我正在寻找一些指导。我并不是真的可以自由地披露数据库架构,所以希望这是足够的信息。谢谢,
SELECT tblA.id, tblB.id, tblC.id, tblD.id
FROM tblA, tblB, tblC, tblD
INNER JOIN (SELECT max(tblB.id) AS xid
FROM tblB
WHERE tblB.rdd = 11305
GROUP BY tblB.index_id
ORDER BY NULL) AS rddx
ON tblB.id = rddx.xid
WHERE
tblA.id = tblB.index_id
AND tblC.name = tblD.s_type
AND tblD.name = tblA.s_name
GROUP BY tblA.s_name
ORDER BY NULL;
:
之间存在一对多的关系+----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+ | 1 | PRIMARY | derived2 | ALL | NULL | NULL | NULL | NULL | 32568 | Using temporary | | 1 | PRIMARY | tblB | eq_ref | PRIMARY | PRIMARY | 8 | rddx.xid | 1 | | | 1 | PRIMARY | tblA | eq_ref | PRIMARY | PRIMARY | 8 | tblB.index_id | 1 | Using where | | 1 | PRIMARY | tblD | eq_ref | PRIMARY | PRIMARY | 22 | tblA.s_name | 1 | Using where | | 1 | PRIMARY | tblC | eq_ref | PRIMARY | PRIMARY | 22 | tblD.s_type | 1 | | | 2 | DERIVED | tblB | ref | rdd_idx | rdd_idx | 7 | | 65722 | Using where; Using temporary | +----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+
答案 0 :(得分:2)
除非我误解了您提供的信息,否则我相信您可以重新编写上述查询,如下所示
EXPLAIN SELECT tblA.id, MAX(tblB.id), tblC.id, tblD.id
FROM tblA
LEFT JOIN tblD ON tblD.name = tblA.s_name
LEFT JOIN tblC ON tblC.name = tblD.s_type
LEFT JOIN tblB ON tblA.id = tblB.index_id
WHERE tblB.rdd = 11305
ORDER BY NULL;
显然我无法为此提供解释,因为解释取决于数据库中的数据。看到关于这个查询的解释会很有趣。
显然,解释只能估计会发生什么。您可以使用SHOW SESSION STATUS来详细说明运行实际查询时发生的情况。确保在运行您正在调查的查询之前运行,以便您可以读取干净的数据。所以在这种情况下你会运行
FLUSH STATUS;
EXPLAIN SELECT tblA.id, MAX(tblB.id), tblC.id, tblD.id
FROM tblA
LEFT JOIN tblD ON tblD.name = tblA.s_name
LEFT JOIN tblC ON tblC.name = tblD.s_type
LEFT JOIN tblB ON tblA.id = tblB.index_id
WHERE tblB.rdd = 11305
ORDER BY NULL;
SHOW SESSION STATUS LIKE 'ha%';
这为您提供了许多指标,用于显示执行查询时实际发生的情况。
Handler_read_rnd_next - Number of requests to read next row in the data file
Handler_read_key - Number of requests to read a row based on a key
Handler_read_next - Number of requests to read the next row in key order
使用这些值,您可以准确了解幕后发生的事情。
不幸的是,如果不知道表中的数据,引擎类型和查询中使用的数据类型,很难就如何优化提出建议。
答案 1 :(得分:1)
我已使用连接而不是WHERE子句中的连接更新了查询。另外,通过查看它,作为开发人员,您可以直接查看表之间的关系。 A-> B,A-> D和D-> C.现在,在表B中,您希望基于公共“ID = Index_ID”的最高ID,并且RDD = 11305将不需要完整的子查询。但是,这已将“MAX()”移动到字段选择子句的上部。我会确保你有一个关于tblB的索引(index_id,rdd)。最后,通过执行STRAIGHT_JOIN将有助于根据具体列出的方式强制执行查询运行。
- 来自评论的编辑 -
看来你从tblB得到了空值。这通常表示有效的tblA记录,但没有相同ID的RDB = 11305的tblB记录。也就是说,看起来你只关心那些与11305相关的条目,所以我相应地调整了查询。请确保您在tblB上有一个基于“RDD”列的索引(至少在多列索引的情况下位于第一个位置)
正如您在本文中所看到的,我仅从表B中查询11305个条目并通过index_ID进行预分组(与tblA链接)。这给了我一个记录,每个索引它们将存在...从这个结果,我加入回A,然后再次直接回到B,但是根据找到的最高匹配ID,然后D和C一如既往。所以现在,您可以从任何表中获取任何列并获得正确的记录...此查询中应该没有剩余的NULL值。
希望我已经澄清了我是如何为你准备的。
SELECT STRAIGHT_JOIN
PreQuery.HighestPerIndexID
tblA.id,
tblA.AnotherAField,
tblA.Etc,
tblB.SomeOtherField,
tblB.AnotherField,
tblC.id,
tblD.id
FROM
( select PQ1.Index_ID,
max( PQ1.ID ) as HighestPerIndexID
from tblB PQ1
where PQ1.RDD = 11305
group by PQ1.Index_ID ) PreQuery
JOIN tblA
on PreQuery.Index_ID = tblA.ID
join tblB
on PreQuery.HighestPerIndexID = tblB.ID
join tblD
on tblA.s_Name = tblD.name
join tblC
on tblD.s_type = tblC.Name
ORDER BY
tblA.s_Name