У меня есть две таблицы человек и город . Таблица person и таблица city связаны с использованием city_id лично. Таблица person содержит около миллионов строк, а таблица city - около 10000 строк.
indexes on person: index1: id, index2: city_id
indexes on city: index1: id
Мне нужно выбрать все те города, которыене иметь строки, связанной с человеком. Таблица city и person выглядит следующим образом (демонстрационные данные).
CITY PERSON
id city id name city_id
------------- ------------------
1 city-1 1 name-1 1
2 city-2 2 name-2 2
3 city-3 3 name-3 2
4 city-4 4 name-4 3
5 city-5 5 name-5 1
6 city-6 6 name-6 3
7 city-7 7 name-7 4
8 city-8 8 name-8 8
Я написал два запроса, чтобы получить результат:
query1:
select c.id, c.city
from city c
left join person p on c.id = p.city_id
where p.id is null
query2:
select *
from city
where id not in ( select distinct city_id from person)
план выполнения обоих запросов выглядит примерно так:
Для запроса 1: для запроса 2:
Затем я использовал профилирование и пару раз выполнил оба запроса, чтобы увидеть, сколько времени они занимают:
query1: 0.000729 0.000737 0.000763
query2: 0.000857 0.000840 0.000852
Очевидно, что запрос данных1 выше, чем запрос2.
Я запутался, поскольку то, что я понимаю, query2 должно превзойти query1 . Поскольку вложенный запрос query2 использует city_id, который проиндексирован, и mysql может использовать city_id index , чтобы получить все id , но query1 использует соединение, которое получит декартово произведение обеих таблиц. Это потому, что я использовал меньше данных f. человек (1000) и город (200) записей .
Чего мне не хватает из-за того, что query1 работает лучше, чем query2.
Редактировать
Из документации mysql:
covering index: An index that includes all the columns retrieved by a query. Instead of using
the index values as pointers to find the full table rows, the query returns values
from the index structure, saving disk I/O
Это было предположение, которое я сделал, когда пришел к запросу2.