[MySql] Оператор сравнения IN
Что-то не могу нагуглить, есть ли у оператора IN ограничения. Сколько значений может принимать этот оператор? 100 принимает, проверено, а 1000? И стоит ли обновлять записи в базе таким запросом на 1000 вхождений или лучше 10 запросов по 100?
|
Ответ: [MySql] Оператор сравнения IN
Скорость работы IN, в зависимости от запроса может умножать сложность запроса кратной элементов в IN.
Так что если делаешь запрос на IN 10 ID например, то это скорее всего приведет к 10 кратному усложнению запроса, следственно в 10 дольше будет генерировать ответ. И это в хорошем случае когда индексы используются. Без индексов все может быть похуже, если первым используется другое поле, и затем из профильтрованных значений нужно делать проверку. То либо будет создаваться мелкий временный индекс по меньшему списку проверямых данных, и еще одна итерация по полям для сравнения, либо вообще O(a*b), что я надеюсь в дб движке избежали используя временный индекс. Если используется временный индекс, то это использует RAM, индексы обычно легкие. Не смотря на все это, использование IN с очень большими списками не рекомендуется. Порой можно избежать подобного и структурировать данные более удобно для таких целей. |
Ответ: [MySql] Оператор сравнения IN
У меня задача - сервер оповещений оптимизировать. Я беру из базы LIMIT offset, 1000 записей, по ним вызываю оповещение в соц сети, потом мне надо этим записям записать дату последней нотификации. Так по всей базе пользователей данной соц сети. Пользователи других соц сетей тоже в этой базе приустствуют. По полю user_id из соц сети у меня есть индекс.
|
Ответ: [MySql] Оператор сравнения IN
Немного запутался когда ты говоришь "база". Ты имеешь ввиду "таблица"?
У тебя в одной таблице все пользователи, с колонкой "соц_сеть"? И тебе нужно пробежаться по всем пользователям определенной соц сети, послать им оповещение (соц. сети API), и затем записать дату оповещения? Я не совсем вижу вообще зачем тебе IN здесь. Сортируешь по user_id (он не изменный и только увеличивается). И далее делаешь выборку например 128 пользователей, далее шлешь им оповещания и обновляешь им notification_date, при этом тут проще будет использовать user_id больше и меньше чем первый и последний в этом списке. Затем делаешь снова ту же выборку, только уже с дополнительным условием: user_id > last_user_id - где last_user_id самый большой последний user_id. И повторяешь все те же операции как и раньше. И так по циклу, пока возвратимый результат не вернет 0 записей. Что-то типо (псевдокод) PHP код:
Также увеличивая размер batch'а (128 в данном примере), ты больше заполнишь оперативки, но можешь быстрее обработать всю таблицу, снизив число запросов и парсинга. Также такие вещи нужно писать не в блокируемом языке, с учетом того что send_notification может блокировать. Если он блокирует (PHP или Python), то у тебя этот скрипт займет ужасно много времени. В идеале тебе нужно делать скрипт где send_notification выполняется паралельно с ограниченным числом. Также лучше вообще параллелить батчи тоже, паралельно обрабатывая скажем 8 пачек по 128 пользователей. В node.js такое легко параллелизуется, и будет очень шустро работать. |
Ответ: [MySql] Оператор сравнения IN
Цитата:
Но тут дело такое - я выбираю только тех пользователей, которые логинились менее месяца назад (во время оповещения кто-то может залогиниться к примеру и нарушить порядок). Плюс АПИ соц сети возвращает id пользователей, которым дошло оповещение. Хотелось бы записать только тех, кому действительно оно дошло. Сервер нотификаций работал в отдельном потоке, так что на работу основного сервера не влиял. Сейчас я его в отдельное приложении вынес. Все пишу на C# (Debian/Mono). |
Ответ: [MySql] Оператор сравнения IN
Цитата:
Следственно в условие запроса можешь добавить что пользователь логинился тогда-то. И даже если кто-то залогинится, это ок, т.к. у тебя сортировка и условие зависят от user_id. Цитата:
Главное не запускай этот скрипт рассылки пока не закончилось выполнение прошлого запуска, и тогда не будет конфликтов. Цитата:
Но нужна паралеллизация по задачкам в процессе. Но это не критично. Зависит как быстро будет работать рассылка на данный момент, если медленно (10+ секунд), то стоит подумать о паралеллизации. |
Ответ: [MySql] Оператор сравнения IN
Ух, ну и спор начался...
Цитата:
PHP код:
В ответах api соц сети получаю id получивших. Это новый список (только часть из тех, кому пытался отправить). Вот их надо обновить, не всех в диапазоне min_id ... max_id. Отсюда IN и вопрос что лучше, 10 запросов по 100 или 1 на 1000. (1000 это в худшем случае, обычно меньше, т.к. многие пользователи отключают нотификейшены). |
Ответ: [MySql] Оператор сравнения IN
Цитата:
Цитата:
Тогда не будет никто влезать если залогинятся. Цитата:
Если смотреть проще, можешь даже делать по одному запросу на LIMIT 100, обрабатывать его в другом потоке. Далее если у тебя по времени влезает в ограничения соц. сети, то делаешь еще запрос, и так по кругу, пока не будешь упираться в ограничения по времени. Таким образом можно будет и паралельно пачками слать, в итоге у тебя будет максимальная скорость рассылки. Т.к. работа с бд у тебя будет по любому в разы быстрее чем их ограничения на api. |
Ответ: [MySql] Оператор сравнения IN
Pax, я повторюсь, используй EXPLAIN для профилирования запросов.
Там наглядно показано как что на производительность влияет. А то тут уже непонятные споры на ровном месте. |
Ответ: [MySql] Оператор сравнения IN
Цитата:
|
Ответ: [MySql] Оператор сравнения IN
Вынес оффтоп сюда: http://forum.boolean.name/showthread.php?t=19986
pax, было бы интересно если ты использовал бы EXPLAIN на все запросы твоего скрипта. И вообще поделился бы в итоге результатами скорости работы SQL запросов, размера таблицы и времени работы всего скрипта на одну рассылку по всем пользователям. |
Ответ: [MySql] Оператор сравнения IN
Это было бы круто, но тестировать на живую сложно. Пока нотификейшен сервер не обновлен в игре и рассылать уведомления просто так не хороший тон. Делать фейковую базу для тестирования нагрузки просто нет времени.
|
Ответ: [MySql] Оператор сравнения IN
Ну ты замерь время выполнения реального скрипта, и кинь в логи, потом поделись данным.
Имхо как разработчик ты же сам должен знать сколько занимают твои скрипты, иначе это слепо надеятся на то что оно как-то работает нормально? |
Ответ: [MySql] Оператор сравнения IN
Когда-нибудь заморочусь над этим. Одно могу сказать точно, при вчерашнем обновлении игры рассылка нотификейшенов прошла быстрее. Но там был комплекс переработок. Нагрузка на БД уменьшилась во время рассылки (чего я и хотел добиться). Вероятно из-за выборки по последнему разосланному id пользователя и выборке по 1000 вместо 100. Нагрузка на CPU увеличилась, но с этим мне еще предстоит разобраться. Полное логирование времени запросов лень делать чисто потому, что нотификейшены мы массово рассылаем раз в неделю две.
|
Ответ: [MySql] Оператор сравнения IN
Но предположим рассылка нотификейшенов занимает 5 минут всего.
Где 2 минуты расходуются на обработку SQL запросов. Это пару раз в неделю, вы будете на этот период сильно снижать производительность других сложных и менее сложных запросов. На 2 минуты ответы от бд будут дольше, это в сценарии если бд юзает очень много CPU и/или IO. Вот и будет неприятно на 2 минуты могут быть лаги. |
Часовой пояс GMT +4, время: 09:38. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot