【发布时间】:2016-05-18 22:23:27
【问题描述】:
所以,这是我的查询:
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;
基本上,有一个名为groups的表,我想找到2个级别内指向group_id=5作为其父级的所有组。这些组通过groups_qids 与一个qids 表相关联,所以我想找到与我刚刚找到的所有这些组相关联的所有qid。
然后,我们有指向 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 秒内运行,返回 10547 行。
按钮表中有 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)
如果我使用返回 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)) |
更多好奇... 对于此查询: 从 qid_id 所在的按钮中选择内容(从 group_qids 中选择不同的 qid_id,其中 group_id = 10); 它也需要永远。而且,有趣的是……那个子查询有 0 个结果,MySQL 可以在 0.00 秒内计算出来。
content 是按钮上的 TEXT 类型,我猜这是问题的很大一部分...(尽管在最后一个查询中,您仍然认为它会立即返回。)这是唯一的表定义的一部分对我来说很突出,但这是完整的:
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 | |
+--------------------+--------------+------+-----+---------+----------------+
【问题讨论】:
-
问题是如果像你这样使用嵌套子查询,你无法预测操作的实际计算成本。我的猜测是,您在“SELECT id FROM groups WHERE parent_id IN (SELECT id FROM groups WHERE parent_id=5))”中的嵌套子查询正在减慢一切。另外,您正在运行 SELECT id FROM groups WHERE parent_id=5 两次,这不是最佳的。我建议您分解查询,单独运行嵌套查询并将它们存储在变量中,将它们联合起来。除此之外,您可以看看 EXISTS 运算符,它运行得更快。
-
请发布您所有相关的表结构,我的意思是创建表代码并显示一些示例输入和预期输出。 @汤姆
-
您应该“加入”表而不是“嵌套”查询。
-
让我把这个简单,我可以做这个查询: 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)) 这给了我大约 10k 的结果,只需要几分之一秒。该查询是一个 ID 列表。然后从那个中间查询中,我想从@thatintermediatequeryresult 中的qid_id 按钮中选择内容;我可以这样做吗?我不认为中间查询有任何性能问题...外部查询搞砸了...
标签: mysql database performance database-design relational-database