gpt4 book ai didi

MySQL Select 不在不同的 Where 值上使用索引

转载 作者:太空宇宙 更新时间:2023-11-03 12:21:37 25 4
gpt4 key购买 nike

我有一个有时完美运行的连接查询我从 EventKeyReference 表中获取 eventKey、label 和 dataUnit,从 EventData 中获取 valueParam,从表 EventHeader 中获取时间戳。在我的 where 子句中,我有 Unit u.id = 3。这很好用。但是,当我尝试搜索 Unit u.id = 1 时,查询有时可能需要长达 20 秒。

搜索 id = 3

SELECT ek.eventKey, ek.label, ek.dataUnit, ed.valueParam, eh.timestamp
FROM EventKeyReference AS ek
INNER JOIN UnitReference_EventKeyReference AS urek ON urek.eventKeyReferences_id = ek.id
INNER JOIN UnitReference AS ur ON ur.id = urek.UnitReference_id
INNER JOIN Unit AS un ON un.id = ur.unit_id INNER JOIN User AS u ON u.id = ur.user_id
INNER JOIN EventData AS ed ON ek.eventKey = ed.keyParam
INNER JOIN EventHeader AS eh ON eh.id = ed.eventHeader_id
WHERE ek.eventKey = 'C004' AND u.id = 3 AND un.serialNumber=221148096
ORDER BY eh.timestamp LIMIT 1;

给出这个:

+----------+----------+----------+------------+---------------------+
| eventKey | label | dataUnit | valueParam | timestamp |
+----------+----------+----------+------------+---------------------+
| C004 | Utgang 2 | on/off | 0 | 2000-01-01 00:01:04 |
+----------+----------+----------+------------+---------------------+
1 row in set (0.00 sec)

搜索 id = 1 得到这个:

+----------+-------------+----------+------------+---------------------+
| eventKey | label | dataUnit | valueParam | timestamp |
+----------+-------------+----------+------------+---------------------+
| C004 | DigitalOut1 | ON/OFF | 0 | 2000-01-01 00:01:04 |
+----------+-------------+----------+------------+---------------------+
1 row in set (16.04 sec)

如您所见,执行查询需要 16 秒。

在检查 EXPLAIN SELECT 时,我明白了。

    mysql> EXPLAIN SELECT ek.eventKey, ek.label, ek.dataUnit, ed.valueParam,    eh.timestamp   FROM EventKeyReference AS ek INNER JOIN UnitReference_EventKeyReference AS urek ON urek.eventKeyReferences_id = ek.id INNER JOIN UnitReference AS ur ON ur.id = urek.UnitReference_id  INNER JOIN Unit AS un ON un.id = ur.unit_id INNER JOIN User AS u ON u.id = ur.user_id INNER JOIN EventData AS ed ON ek.eventKey = ed.keyParam INNER JOIN EventHeader AS eh ON eh.id = ed.eventHeader_id   WHERE ek.eventKey = 'C004' AND u.id = 1 AND un.serialNumber=221148096 ORDER BY eh.timestamp DESC LIMIT 1;
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+--------+----------------------------------------------+
| 1 | SIMPLE | u | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | eh | index | PRIMARY | eh_timestamp | 9 | NULL | 169161 | Using index |
| 1 | SIMPLE | ed | ref | FK794A194417A622D6 | FK794A194417A622D6 | 9 | fltcoor.eh.id | 5 | Using where |
| 1 | SIMPLE | ur | range | PRIMARY,FK83382A0747140EFE,FK83382A073EC5085E | FK83382A0747140EFE | 9 | NULL | 3 | Using where; Using join buffer |
| 1 | SIMPLE | urek | ref | PRIMARY,FKAC98AB0E2DFCBD8F,FKAC98AB0E564AEB96 | FKAC98AB0E564AEB96 | 8 | fltcoor.ur.id | 11 | Using index |
| 1 | SIMPLE | un | eq_ref | PRIMARY,serialNumber | PRIMARY | 8 | fltcoor.ur.unit_id | 1 | Using where |
| 1 | SIMPLE | ek | eq_ref | PRIMARY | PRIMARY | 8 | fltcoor.urek.eventKeyReferences_id | 1 | Using where |
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+--------+----------------------------------------------+
7 rows in set (0.00 sec)

mysql> EXPLAIN SELECT ek.eventKey, ek.label, ek.dataUnit, ed.valueParam, eh.timestamp FROM EventKeyReference AS ek INNER JOIN UnitReference_EventKeyReference AS urek ON urek.eventKeyReferences_id = ek.id INNER JOIN UnitReference AS ur ON ur.id = urek.UnitReference_id INNER JOIN Unit AS un ON un.id = ur.unit_id INNER JOIN User AS u ON u.id = ur.user_id INNER JOIN EventData AS ed ON ek.eventKey = ed.keyParam INNER JOIN EventHeader AS eh ON eh.id = ed.eventHeader_id WHERE ek.eventKey = 'C004' AND u.id = 3 AND un.serialNumber=221148096 ORDER BY eh.timestamp DESC LIMIT 1;
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+------+-------------+
| 1 | SIMPLE | u | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index |
| 1 | SIMPLE | eh | index | PRIMARY | eh_timestamp | 9 | NULL | 1 | Using index |
| 1 | SIMPLE | ur | ref | PRIMARY,FK83382A0747140EFE,FK83382A073EC5085E | FK83382A0747140EFE | 9 | const | 2 | Using where |
| 1 | SIMPLE | un | eq_ref | PRIMARY,serialNumber | PRIMARY | 8 | fltcoor.ur.unit_id | 1 | Using where |
| 1 | SIMPLE | ed | ref | FK794A194417A622D6 | FK794A194417A622D6 | 9 | fltcoor.eh.id | 5 | Using where |
| 1 | SIMPLE | urek | ref | PRIMARY,FKAC98AB0E2DFCBD8F,FKAC98AB0E564AEB96 | FKAC98AB0E564AEB96 | 8 | fltcoor.ur.id | 11 | Using index |
| 1 | SIMPLE | ek | eq_ref | PRIMARY | PRIMARY | 8 | fltcoor.urek.eventKeyReferences_id | 1 | Using where |
+----+-------------+-------+--------+-----------------------------------------------+--------------------+---------+------------------------------------+------+-------------+
7 rows in set (0.00 sec)

出于某种原因,在 id = 1 的查询中,MYSQL 会处理大约 16.000 行。

这一直困扰着我一整天,因为我找不到为什么会发生这种情况。如果有任何更多信息,我很乐意提供,因为我自己远非 Mysql 专家。

最佳答案

正如 Jakob 所说,如果您有 160000 个用户 1 的条目,那可能是您的瓶颈。我已经重写希望能有所帮助。我更改了顺序,希望将最小的粒度部分放在查询的主要位置并从中链接起来。我怀疑给定序列号的记录很少,因此将其放入 WHERE 子句并添加次要的 JOIN 条件(通过实现的 ON/AND 子句)应该会有所帮助。

SELECT 
ek.eventKey,
ek.label,
ek.dataUnit,
ed.valueParam,
eh.timestamp
FROM
Unit AS un
INNER JOIN UnitReference AS ur
ON un.id = ur.unit_id
AND ur.user_id = 3 <== ADDED USER ID CRITERIA HERE
INNER JOIN User AS u
ON ur.user_id = u.id
INNER JOIN UnitReference_EventKeyReference AS urek
ON ur.id = urek.UnitReference_id
INNER JOIN EventKeyReference AS ek
ON urek.eventKeyReferences_id = ek.id
AND ek.eventKey = 'C004' <== ADDED EVENT KEY CRITERIA HERE
INNER JOIN EventData AS ed
ON ek.eventKey = ed.keyParam
INNER JOIN EventHeader AS eh
ON ed.eventHeader_id = eh.id
WHERE
un.serialNumber=221148096
ORDER BY
eh.timestamp LIMIT 1;

如果上述方法不起作用,我会尝试的唯一其他项目,并且因为它是 MySQL,我会再添加一个关键字...

SELECT STRAIGHT_JOIN [查询的其余部分]

它告诉 MySQL 按照您指定的顺序进行查询,而不是尝试以不同的顺序为您考虑。

关于MySQL Select 不在不同的 Where 值上使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19637559/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com