@easycode
не боюсь задавать глупые вопросы ))

Как оптимизировать SQL-запрос (или MySQL-таблицу) для ускорения его выполнения?

Имеется такая MySQL-таблица:
CREATE TABLE IF NOT EXISTS `mails` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `to` varchar(255) NOT NULL,
  `object` varchar(30) NOT NULL,
  `data` text NOT NULL,
  `temp_id` int(11) NOT NULL,
  `mailing_id` int(11) NOT NULL,
  `priority` tinyint(1) NOT NULL,
  `send_time` datetime NOT NULL,
  `error` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;


Таблица наполнена данными, сейчас порядка: 350 тыс. записей.

В цикле к данной таблице выполняется несколько тысяч запросов (3000-10000 штук) одного и того же вида:

SELECT `id`, `to` FROM `mails` WHERE (`to` LIKE 'info@mail.ru' OR `to` LIKE 'info@mail.ru,%' OR `to` LIKE '%,info@mail.ru' OR `to` LIKE '%,info@mail.ru,%') AND `mailing_id` = 172


Вопрос: как оптимизировать данный SQL-запрос (или саму MySQL-таблицу) для увеличения скорости его выполнения?


p.s.: запрос выполняется в Yii 1.x через конструктор запросов: Yii::app()->db->createCommand()->select("id, to")->from('{{mails}}')....
  • Вопрос задан
  • 671 просмотр
Пригласить эксперта
Ответы на вопрос 6
romy4
@romy4
Exception handler
выполняйте не несколько тысяч запросов, а один. избавтесь от бесполезного цикла в первую. даже в нулевую очередь!
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Выносить адреса в отдельную таблицу и делать связь многие-ко-многим. Поиск через LIKE, если маска начинается с %, - очень затратная и не использующая индексы операция.
Ответ написан
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
несколько тысяч запросов (3000-10000 штук) одного и того же вида

зачем? почему? да как же так? ужос нах. катастрофа. пииииипец. Как после этой фразы можно спрашивать "что оптимизировать?". Вот это и оптимизировать. Убрать к чертям и написать 1 запрос. Нагрузка спадет в разы, а потом уже копеечки можно донабрать за счет индексов.
Ответ написан
dude_sam
@dude_sam
BI Developer
Создать составной индекс по полям `to` и 'mailing_id`.
Условие WHERE заменить на JOIN.
Ну, и обязательно "несколько тысяч запросов" заменить на один.
Ответ написан
@easycode Автор вопроса
не боюсь задавать глупые вопросы ))
Изначально, не дописал один важный момент: таблица mails содержит в себе письма в разных статусах: в очереди, отправлено и т.д. Мой сумасшедший цикл выполняющий медленный запрос с LIKE'ами - неизбежен при таком функционале: у клиента есть рассылка писем по базе адресов, база адресов очень большая (более 100 тыс.) и главное что используется в разных местах огромной системы, ну и самое плохое: email'ы пишутся через запятую в одном поле и могут повторяться для разных записей из базы рассылки, потому я и использовал LIKE'и чтобы не отправить на один и тот же Email адрес более одного письма.

Функционал такой конечно же надо переписывать - это понятно, но очень много зависимостей, смежного функционала и т.д. - это всё большой объем работы, а нужно бы быстрое решение.

В рамках одного процесса формирования писем создается не более 10 тыс. писем. Потому я думаю пока лучшим временным решением будет создание промежуточной таблицы содержащий все email адреса для формирующихся писем по одному адресу в одной записи в одном поле. Таким образом, не нужно будет юзать LIKE'и, плюс сама таблица будет содержать максимум 3 поля и не содержать более 10 тыс. записей.

Всем спасибо за комментарии и ответы!
Если вдруг появятся еще свежие идеи по моей проблеме пожалуйста напишите здесь!
Ответ написан
Комментировать
@stuk_alex
зачем перебирать все варианты LIKE? Вполне достаточно одного оператора LIKE
SELECT `id`, `to` FROM `mails` WHERE `to` LIKE '%info@mail.ru%' AND `mailing_id` = 172
можно ли придумать обход в цикле немного по-другому, чтобы сократить количество итераций? мало данных, что означает mailing_id? можно ли объединить другими значениями и сделать mailing_id IN (...)?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы