| Bug #25130 | Extremely Slow "Where in (Select... )" Subqueries GROUP BY / HAVING related | ||
|---|---|---|---|
| Submitted: | 18 Dec 2006 5:46 | Modified: | 26 Mar 2012 19:41 |
| Reporter: | Ashleigh Gordon | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
| Version: | 5.0.34-BK, 5.0.27, 5.1, 5.5.0 | OS: | Windows (Windows, Sparc & Linux) |
| Assigned to: | CPU Architecture: | Any | |
[18 Dec 2006 5:46]
Ashleigh Gordon
[18 Dec 2006 5:47]
Ashleigh Gordon
Contains 3 files. Two to recreate tables and data, the other is an example of the problem query.
Attachment: Sample_SQL.zip (application/x-zip-compressed, text), 14.39 KiB.
[18 Dec 2006 22:46]
Valeriy Kravchuk
Thank you for a problem report. Verified just as described with 5.0.34-BK on Linux:
mysql> explain extended Select count(key_id) from Patients where key_id in ( S
ELECT DISTINCT Evals.Patient_ID FROM Evals INNER JOIN Patients ON Patients.Key_
ID = Evals.Patient_ID WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1
) and (Patients.key_id < 820) GROUP BY Evals.Patient_ID HAVING
(COUNT(Evals.Patient_ID) > 0) )\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: Patients
type: index
possible_keys: NULL
key: PRIMARY
key_len: 8
ref: NULL
rows: 1200
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: Evals
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3600
Extra: Using where; Using temporary; Using filesort
*************************** 3. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: Patients
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: test.Evals.Patient_ID
rows: 1
Extra: Using where
3 rows in set, 1 warning (0.00 sec)
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: select count(`test`.`Patients`.`Key_ID`) AS `count(key_id)` from `test`.`Patients` where <in_optimizer>(`test`.`Patients`.`Key_ID`,<exists>
(select distinct `test`.`Evals`.`Patient_ID` AS `Patient_ID` from `test`.`Evals` join `test`.`Patients` where ((`test`.`Patients`.`Center_ID` = 1) and (`test`.`Evals`.`Location_id` = 1) and (`test`.`Patients`.`Key_ID` < 820) and (`test`.`Patients`.`Key_ID` = `test`.`Evals`.`Patient_ID`))
group by `test`.`Evals`.`Patient_ID` having ((count(`test`.`Evals`.`Patient_ID`) > 0) and (<cache>(`test`.`Patients`.`Key_ID`) = <ref_null_helper>(
`test`.`Evals`.`Patient_ID`)))))
1 row in set (0.00 sec)
mysql> Select count(key_id) from Patients where key_id in ( SELECT DISTINCT Ev
als.Patient_ID FROM Evals INNER JOIN Patients ON Patients.Key_ID = Evals.Patien
t_ID WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1) and (Patients.k
ey_id < 820) GROUP BY Evals.Patient_ID HAVING (COUNT(Evals
.Patient_ID) > 0) )\G
*************************** 1. row ***************************
count(key_id): 819
1 row in set (50.03 sec)
mysql> select version();
+--------------+
| version() |
+--------------+
| 5.0.34-debug |
+--------------+
1 row in set (0.00 sec)
But, please, do not expect this problem to be fixed soon. Wait for MySQL 5.2. Work in progress.
[12 May 2008 14:21]
Jeremy Pointer
Anyone else coming across this problem there is a way around it by using a named subquery as below:
Select count(key_id)
from patients
where key_id in
(
SELECT evsub.Patient_ID
FROM (
SELECT COUNT(Evals.Patient_ID) as cnt, Evals.Patient_ID
FROM Evals INNER JOIN Patients ON Patients.Key_ID = Evals.Patient_ID
WHERE
(Evals.Location_ID = 1)
AND (Patients.Center_ID = 1)
AND (Patients.key_id< 820)
GROUP BY Evals.Patient_ID
) as evsub
where evsub.cnt>1
)
[30 Nov 2009 19:12]
Valeriy Kravchuk
This is fixed in 6.0.14:
77-52-1-11:6.0-codebase openxs$ bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 6.0.14-alpha-debug Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> Select count(key_id) from Patients
-> where key_id in
-> (SELECT DISTINCT Evals.Patient_ID
-> FROM Evals INNER JOIN
-> Patients ON Patients.Key_ID = Evals.Patient_ID
-> WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1) and (Patients.key_id< 820)
-> GROUP BY Evals.Patient_ID
-> HAVING COUNT(Evals.Patient_ID) > 0)
-> ;
+---------------+
| count(key_id) |
+---------------+
| 819 |
+---------------+
1 row in set (0.10 sec)
mysql> explain Select count(key_id) from Patients
-> where key_id in
-> (SELECT DISTINCT Evals.Patient_ID
-> FROM Evals INNER JOIN
-> Patients ON Patients.Key_ID = Evals.Patient_ID
-> WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1) and (Patients.key_id< 820)
-> GROUP BY Evals.Patient_ID
-> HAVING COUNT(Evals.Patient_ID) > 0)
-> ;
+----+-------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
| 1 | PRIMARY | Patients | index | NULL | PRIMARY | 8 | NULL | 1200 | Using where; Using index |
| 2 | SUBQUERY | Evals | ALL | NULL | NULL | NULL | NULL | 3600 | Using where; Using temporary; Using filesort |
| 2 | SUBQUERY | Patients | eq_ref | PRIMARY | PRIMARY | 8 | test.Evals.Patient_ID | 1 | Using index condition; Using where |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
3 rows in set (0.00 sec)
but NOT fixed in 5.5.0 or any other 5..x.y:
77-52-1-11:trunk openxs$ bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.5.0-beta-debug Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> Select count(key_id) from Patients
-> where key_id in
-> (SELECT DISTINCT Evals.Patient_ID
-> FROM Evals INNER JOIN
-> Patients ON Patients.Key_ID = Evals.Patient_ID
-> WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1) and (Patients.key_id< 820)
-> GROUP BY Evals.Patient_ID
-> HAVING COUNT(Evals.Patient_ID) > 0)
-> ;
+---------------+
| count(key_id) |
+---------------+
| 819 |
+---------------+
1 row in set (1 min 6.71 sec)
mysql> explain Select count(key_id) from Patients
-> where key_id in
-> (SELECT DISTINCT Evals.Patient_ID
-> FROM Evals INNER JOIN
-> Patients ON Patients.Key_ID = Evals.Patient_ID
-> WHERE (Evals.Location_ID = 1) AND (Patients.Center_ID = 1) and (Patients.key_id< 820)
-> GROUP BY Evals.Patient_ID
-> HAVING COUNT(Evals.Patient_ID) > 0)
-> ;
+----+--------------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
| 1 | PRIMARY | Patients | index | NULL | PRIMARY | 8 | NULL | 1200 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | Evals | ALL | NULL | NULL | NULL | NULL | 3600 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | Patients | eq_ref | PRIMARY | PRIMARY | 8 | test.Evals.Patient_ID | 1 | Using where |
+----+--------------------+----------+--------+---------------+---------+---------+-----------------------+------+----------------------------------------------+
3 rows in set (0.36 sec)
[26 Mar 2012 19:41]
Paul DuBois
Noted in 5.6.5 changelog. Several subquery performance issues were resolved through the implementation of semi-join subquery optimization strategies.
