Jestem ciekawy, jak wykonanie EXISTS()
ma być szybsze niż IN()
.Mysql Exists vs IN - skorelowane podzapytanie vs podzapytanie?
Byłem answering a question kiedy Bill Karwin przedstawił dobry punkt. podczas korzystania z EXISTS()
używa skorelowanego podkwerendy (podzapytanie zależne), a IN() używa tylko podkwerendy.
EXPLAIN pokazuje, że EXISTS
i NOT EXISTS
stosowania zarówno zależną podzapytania i IN/NOT IN
zarówno używać tylko podkwerenda .. więc jestem ciekaw jak skorelowane podzapytanie jest szybszy niż podkwerendzie ??
Używałem EXISTS wcześniej i wykonuje się szybciej niż IN, dlatego jestem zdezorientowany.
Oto SQLFIDDLE z wyjaśnia
EXPLAIN SELECT COUNT(t1.table1_id)
FROM table1 t1
WHERE EXISTS
( SELECT 1
FROM table2 t2
WHERE t2.table1_id <=> t1.table1_id
);
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY |KEY_LEN | REF | ROWS | EXTRA |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| 1 | PRIMARY | t1 | index | (null) | PRIMARY | 4 | (null) | 4 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | t2 | REF | table1_id | table1_id| 4 | db_9_15987.t1.table1_id | 1 | Using where; Using index |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
EXPLAIN SELECT COUNT(t1.table1_id)
FROM table1 t1
WHERE NOT EXISTS
( SELECT 1
FROM table2 t2
WHERE t2.table1_id = t1.table1_id
);
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY |KEY_LEN | REF | ROWS | EXTRA |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| 1 | PRIMARY | t1 | index | (null) | PRIMARY | 4 | (null) | 4 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | t2 | ref | table1_id | table1_id| 4 | db_9_15987.t1.table1_id | 1 | Using index |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
EXPLAIN SELECT COUNT(t1.table1_id)
FROM table1 t1
WHERE t1.table1_id NOT IN
( SELECT t2.table1_id
FROM table2 t2
);
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY |KEY_LEN | REF | ROWS | EXTRA |
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+
| 1 | PRIMARY | t1 | index | (null) | PRIMARY | 4 | (null) | 4 | Using where; Using index |
| 2 | SUBQUERY | t2 | index | (null) | table1_id| 4 | (null) | 2 | Using index |
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+
kilka pytań
W wyjaśniono powyżej, w jaki sposób mają using where
EXISTS i using index
w dodatkach, ale NOT EXISTS nie ma using where
w dodatkach?
W jaki sposób skorelowane podzapytanie jest szybsze niż podzapytanie?
Czy masz repro z "exist", które działa szybciej? Również w jakiej wersji tego doświadczyłeś? 'in' również [kiedyś miał ten sam problem] (http://stackoverflow.com/q/3416076/73226) –
@MartinSmith dobrze Zmieniłem moje zapytania z IN na EXISTS około rok temu, ponieważ zostały wykonane szybciej dzięki EXISTS (nie przez cały czas, coś jak pół sekundy do sekundy szybciej) .. ale właśnie dostałem nowy komputer i pobrałem najnowszą wersję MySQL .. Właśnie uruchomiłem zapytanie i IN działało szybciej o .004 sekundy ... czy była ostatnio poprawka dla planu wykonawczego/optymalizatora? –
Nie wiem zbyt wiele na temat optymalizatora MySql, ale uważam, że 5.6 wprowadził pewne zmiany. https://dev.mysql.com/doc/refman/5.6/en/subquery-optymizacja.html –