#mysql #performance #join #inner-join
#mysql #Производительность #Присоединиться #внутреннее объединение
Вопрос:
У меня есть следующие таблицы:
CREATE TABLE smalltable (
smalltable_id VARCHAR(64) NOT NULL,
bigtable_id VARCHAR(64),
...
PRIMARY KEY (smalltable_id)
) ENGINE=InnoDB;
CREATE TABLE bigtable (
bigtable_id VARCHAR(64) NOT NULL,
count BIGINT,
PRIMARY KEY (bigtable_id)
) ENGINE=InnoDB;
smalltable
имеет около 8000 строк и bigtable
около 40 миллионов. Я хотел бы получить эти строки из smalltable
того smalltable.bigtable_id
места, где они присутствуют в bigtable
. Выполнение следующего запроса заняло почти 10 часов:
SELECT * FROM smalltable
INNER JOIN bigtable
ON smalltable.bigtable_id = bigtable.bigtable_id;
Вот результат EXPLAIN
:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: smalltable
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 8610
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: bigtable
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 38818260
filtered: 100.00
Extra: Using where; Using join buffer (Block Nested Loop)
Я не эксперт в интерпретации этого, но похоже, что MySQL выполняет последовательное сканирование обеих таблиц. Если я напишу небольшой скрипт на Python, который перебирает все строки в smalltable
и выполняет SELECT
запрос на bigtable
для каждой строки в smalltable
, все это завершится за 25 секунд. Я хотел бы иметь такую же производительность с одним SQL-запросом.
Комментарии:
1. Добавьте индекс в smalltable (bigtable_id)
2. Спасибо. Это действительно значительно ускоряет процесс. Запрос теперь занимает 1 минуту 30 секунд. Тем не менее, все еще медленнее, чем ручная итерация по smalltable и запуск запросов select к bigtable. Кроме того, было бы неплохо иметь решение, которое не требует изменения smalltable. В реальном варианте использования данные в smalltable являются подмножеством другой большой таблицы, и у меня нет прав на запись для этой таблицы.
3. Индексы — это то, что нужно. Альтернатива — делать то, что вы уже делаете.
4. Проверьте значение
COLLATION
bigtable_id
в обеих таблицах — оно должно быть одинаковым.5. Что такое настройка
join_buffer_size
? Какая версия MySQL?
Ответ №1:
Проверьте путь оптимизатора, какая таблица является основным источником, так как, если она медленная, bigtable используется в качестве основного источника. попробуйте это:
SELECT STRAIGHT_JOIN * FROM smalltable
INNER JOIN bigtable
ON smalltable.bigtable_id = bigtable.bigtable_id;
Использование STRAIGHT_JOIN подскажет mysql следовать порядку таблиц в вашем запросе.
Ответ №2:
Если вам нужна только информация из smalltable
(что подразумевает ваше описание),
SELECT *
FROM smalltable AS s
WHERE EXISTS (
SELECT *
FROM bigtable
WHERE bigtable_id = s.bigtable_id );