MySQL 查询耗时超过 15 分钟,似乎没有那么多数据
MySQL query takes over 15 minutes, doesn't seem like its THAT much data
所以,这是我的查询:
SELECT content FROM buttons WHERE qid_id in
(SELECT distinct qid_id FROM groups_qids WHERE group_id IN
(SELECT 5
UNION
SELECT id FROM groups WHERE parent_id=5
UNION
SELECT id FROM groups WHERE parent_id IN
(SELECT id FROM groups WHERE parent_id=5)))
button_type_id=8;
基本上,有一个叫做组的table,我想找到2级以内指向group_id=5的所有组作为其父组。这些组与 qids table 到 groups_qids 相关联,因此我想找到与我刚刚找到的所有这些组相关联的所有 qids。
然后,我们有指向 qid 的按钮,所以我想在上面计算的列表中找到所有 qid 指向 qid 的按钮。
令人惊讶的是子查询:
select distinct qid_id from groups_qids where group_id in
(select 5
union
select id from groups where parent_id=5
union
select id from groups where parent_id
in (select id from groups where parent_id=5));
-- 将在 0.37 秒内 运行,return 生成 10547 行。
按钮 table 中有 99770 行。
此外,这里是 EXPLAIN 的输出:
mysql> explain select content from buttons where qid_id in (select distinct qid_id from groups_qids where group_id in (select 5 union select id from groups where parent_id=5 union select id from groups where parent_id in (select id from groups where parent_id=5))) and button_type_id=8;
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
| 1 | PRIMARY | buttons | ALL | NULL | NULL | NULL | NULL | 91710 | Using where |
| 2 | DEPENDENT SUBQUERY | groups_qids | ALL | NULL | NULL | NULL | NULL | 11133 | Using where; Using temporary |
| 3 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 4 | DEPENDENT UNION | groups | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| 5 | DEPENDENT UNION | groups | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| 6 | DEPENDENT SUBQUERY | groups | unique_subquery | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| NULL | UNION RESULT | <union3,4,5> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
7 rows in set (0.00 sec)
如果我使用 return 有 211 行(而不是 10547 行)的子查询,查询仍然会卡住。
mysql> show full processlist;
| 634878 | root | localhost | qid | Query | 104 | Sending data | select content from buttons where qid_id in (select distinct qid_id from groups_qids where group_id in (select 10 union select id from groups where parent_id=10)) |
更多好奇心...
对于这个查询:
select 来自 qid_id 按钮的内容(select 与 groups_qids 不同的 qid_id,其中 group_id = 10);
它也需要永远。而且,有趣的是......那个子查询有 0 个结果,并且 MySQL 可以在 0.00 秒内计算出来。
content 是按钮上的 TEXT 类型,我猜这是这里问题的很大一部分......(虽然在最后一个查询中,你仍然认为它 return立即。)这是 table 定义中唯一让我印象深刻的部分,但这里是完整的部分:
mysql> desc buttons;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| key | varchar(50) | NO | | NULL | |
| qid_id | int(11) | NO | MUL | NULL | |
| button_type_id | int(11) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| sort | int(11) | NO | | NULL | |
| img | varchar(50) | NO | | NULL | |
| img_ext | varchar(6) | NO | | NULL | |
| parent | tinyint(1) | NO | | 0 | |
| enabled | tinyint(1) | NO | | NULL | |
| share_gate | tinyint(1) | NO | | NULL | |
| deleted | tinyint(1) | NO | | NULL | |
| qr_id | int(11) | NO | | NULL | |
| function_type | varchar(255) | NO | | NULL | |
| function_folder_id | int(11) | NO | | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
(1) 尝试将索引放在q_id中。 (2) 不使用IN
,尝试加入子查询
SELECT content FROM buttons btns
JOIN
(SELECT distinct qid_id FROM groups_qids WHERE group_id IN
(SELECT 5
UNION
SELECT id FROM groups WHERE parent_id=5
UNION
SELECT id FROM groups WHERE parent_id IN
(SELECT id FROM groups WHERE parent_id=5))) tbl ON tbl.qid_id = btns.qid_id
WHERE btns.button_type_id=8;
所以,这是我的查询:
SELECT content FROM buttons WHERE qid_id in
(SELECT distinct qid_id FROM groups_qids WHERE group_id IN
(SELECT 5
UNION
SELECT id FROM groups WHERE parent_id=5
UNION
SELECT id FROM groups WHERE parent_id IN
(SELECT id FROM groups WHERE parent_id=5)))
button_type_id=8;
基本上,有一个叫做组的table,我想找到2级以内指向group_id=5的所有组作为其父组。这些组与 qids table 到 groups_qids 相关联,因此我想找到与我刚刚找到的所有这些组相关联的所有 qids。
然后,我们有指向 qid 的按钮,所以我想在上面计算的列表中找到所有 qid 指向 qid 的按钮。
令人惊讶的是子查询:
select distinct qid_id from groups_qids where group_id in
(select 5
union
select id from groups where parent_id=5
union
select id from groups where parent_id
in (select id from groups where parent_id=5));
-- 将在 0.37 秒内 运行,return 生成 10547 行。
按钮 table 中有 99770 行。
此外,这里是 EXPLAIN 的输出:
mysql> explain select content from buttons where qid_id in (select distinct qid_id from groups_qids where group_id in (select 5 union select id from groups where parent_id=5 union select id from groups where parent_id in (select id from groups where parent_id=5))) and button_type_id=8;
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
| 1 | PRIMARY | buttons | ALL | NULL | NULL | NULL | NULL | 91710 | Using where |
| 2 | DEPENDENT SUBQUERY | groups_qids | ALL | NULL | NULL | NULL | NULL | 11133 | Using where; Using temporary |
| 3 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 4 | DEPENDENT UNION | groups | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| 5 | DEPENDENT UNION | groups | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| 6 | DEPENDENT SUBQUERY | groups | unique_subquery | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
| NULL | UNION RESULT | <union3,4,5> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------------+--------------+-----------------+---------------+---------+---------+------+-------+------------------------------+
7 rows in set (0.00 sec)
如果我使用 return 有 211 行(而不是 10547 行)的子查询,查询仍然会卡住。
mysql> show full processlist;
| 634878 | root | localhost | qid | Query | 104 | Sending data | select content from buttons where qid_id in (select distinct qid_id from groups_qids where group_id in (select 10 union select id from groups where parent_id=10)) |
更多好奇心... 对于这个查询: select 来自 qid_id 按钮的内容(select 与 groups_qids 不同的 qid_id,其中 group_id = 10); 它也需要永远。而且,有趣的是......那个子查询有 0 个结果,并且 MySQL 可以在 0.00 秒内计算出来。
content 是按钮上的 TEXT 类型,我猜这是这里问题的很大一部分......(虽然在最后一个查询中,你仍然认为它 return立即。)这是 table 定义中唯一让我印象深刻的部分,但这里是完整的部分:
mysql> desc buttons;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| key | varchar(50) | NO | | NULL | |
| qid_id | int(11) | NO | MUL | NULL | |
| button_type_id | int(11) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| sort | int(11) | NO | | NULL | |
| img | varchar(50) | NO | | NULL | |
| img_ext | varchar(6) | NO | | NULL | |
| parent | tinyint(1) | NO | | 0 | |
| enabled | tinyint(1) | NO | | NULL | |
| share_gate | tinyint(1) | NO | | NULL | |
| deleted | tinyint(1) | NO | | NULL | |
| qr_id | int(11) | NO | | NULL | |
| function_type | varchar(255) | NO | | NULL | |
| function_folder_id | int(11) | NO | | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
(1) 尝试将索引放在q_id中。 (2) 不使用IN
,尝试加入子查询
SELECT content FROM buttons btns
JOIN
(SELECT distinct qid_id FROM groups_qids WHERE group_id IN
(SELECT 5
UNION
SELECT id FROM groups WHERE parent_id=5
UNION
SELECT id FROM groups WHERE parent_id IN
(SELECT id FROM groups WHERE parent_id=5))) tbl ON tbl.qid_id = btns.qid_id
WHERE btns.button_type_id=8;