Фон
У меня есть тестовая среда MySQL с таблицей, которая содержит более 200 миллионов строк.По этой таблице необходимо выполнить два типа запросов;
- Есть ли определенные строки.Учитывая
client_id
и список sgtin
с, которые могут содержать до 50 000 элементов, мне нужно знать, какие sgtin
с присутствуют в таблице. - Выберите эти строки.Учитывая
client_id
и список sgtin
с, которые могут вместить до 50 000 элементов, мне нужно получить полный ряд.(store, gtin ...)
Таблица может увеличиться до 200+ миллионов записей для одного 'client_id'.
Тестовая среда
Xeon E3-1545M / 32GB RAM / SSD.InnoDB буферный пул 24 ГБ.(Производством будет сервер большего размера с 192 ГБ ОЗУ)
Таблица
CREATE TABLE `sgtins` (
`client_id` INT UNSIGNED NOT NULL,
`sgtin` varchar(255) NOT NULL,
`store` varchar(255) NOT NULL,
`gtin` varchar(255) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX (`client_id`, `store`, `sgtin`),
INDEX (`client_id`),
PRIMARY KEY (`client_id`,`sgtin`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Тесты
Первый случайный случайЗначения sgtin распределены по 10 'client_id's, чтобы заполнить таблицу 200 миллионами строк.
Я создал инструмент для тестирования, который выполняет различные запросы, которые я пробовал.Также я использовал план объяснения, чтобы выяснить, какая производительность лучше.Этот инструмент будет читать для каждого теста новые случайные данные из данных, которые я использовал для заполнения базы данных.Чтобы убедиться, что каждый запрос отличается.
Для этого поста я буду использовать 28 sgtin
с. Временная таблица
CREATE TEMPORARY TABLE sgtins_tmp_table (`sgtin` varchar(255) primary key)
engine=MEMORY;
Существующий запрос
Я использую этот запрос, чтобы выяснить, существуют ли sgtin
s.Также это самый быстрый запрос, который я нашел.Для 50K sgtin
с этот запрос займет от 3 до 9 секунд.
-- cost = 17 for 28 sgtins loaded in the temp table.
SELECT sgtin
FROM sgtins_tmp_table
WHERE EXISTS
(SELECT sgtin FROM sgtins
WHERE sgtins.client_id = 4
AND sgtins.sgtin = sgtins_tmp_table.sgtin);
![Explain plan](https://i.stack.imgur.com/d5mFq.png)
Выбор запросов
-- cost = 50.60 for 28 sgtins loaded in the temp table. 50K not usable.
SELECT sgtins.sgtin, sgtins.store, sgtins.timestamp
FROM sgtins_tmp_table, sgtins
WHERE sgtins.client_id = 4
AND sgtins_tmp_table.sgtin = sgtins.sgtin;
![Explain plan](https://i.stack.imgur.com/N58u1.png)
-- cost = 64 for 28 sgtins loaded in the temp table.
SELECT sgtins.sgtin, sgtins.store, sgtins.timestamp
FROM sgtins
WHERE sgtins.client_id = 4
AND sgtins.sgtin IN ( SELECT sgtins_tmp_table.sgtin
FROM sgtins_tmp_table);
![Explain plan](https://i.stack.imgur.com/uFoNG.png)
-- cost = 50.60 for 28 sgtins loaded in the temp table.
SELECT sgtins_tmp_table.epc, sgtins.store
FROM sgtins_tmp_table, sgtins
WHERE exists (SELECT organization_id, sgtin FROM sgtins WHERE client_id = 4 AND sgtins.sgtin = sgtins_tmp_table.sgtin)
AND sgtins.client_id = 4
AND sgtins_tmp_table.sgtin = sgtins.sgtin;
![Explain plan](https://i.stack.imgur.com/IwpfV.png)
Сводка
Существующий запрос пригоден для использования, но выбор выполняется медленно.Что я могу с этим поделать?И любые советы приветствуются:)