Мне нужно написать запрос, чтобы получить большой список идентификаторов.
Мы поддерживаем множество бэкэндов (MySQL, Firebird, SQLServer, Oracle, PostgreSQL ...), поэтому мне нужно написать стандартный SQL.
Размер набора идентификаторов может быть большим, запрос будет сгенерирован программно. Итак, каков наилучший подход?
1) Написание запроса с использованием IN
SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)
Мой вопрос здесь Что будет, если n очень большое? Кроме того, как насчет производительности?
2) Написание запроса с использованием ИЛИ
SELECT * FROM TABLE WHERE ID = id1 OR ID = id2 OR ... OR ID = idn
Я думаю, что у этого подхода нет предела n, но как насчет производительности, если n очень велико?
3) Написание программного решения:
foreach (var id in myIdList)
{
var item = GetItemByQuery("SELECT * FROM TABLE WHERE ID = " + id);
myObjectList.Add(item);
}
У нас возникли некоторые проблемы с этим подходом, когда сервер баз данных запрашивается по сети. Обычно лучше сделать один запрос, который извлекает все результаты, а не много маленьких запросов. Может я не прав.
Каково было бы правильное решение этой проблемы?
IN
! Я выбрал в качестве вашего решения 1 + 3. Просто последний запрос был одной длинной строкой запроса, отправленной в SQL для выполнения.Ответы:
Вариант 1 является единственным хорошим решением.
Зачем?
Вариант 2 делает то же самое, но вы повторяете имя столбца много раз; Кроме того, механизм SQL не сразу знает, что вы хотите проверить, является ли значение одним из значений в фиксированном списке. Тем не менее, хороший движок SQL может оптимизировать его, чтобы иметь равную производительность, как с
IN
. Там все еще проблема читабельности, хотя ...Вариант 3 просто ужасен с точки зрения производительности. Он отправляет запрос каждый цикл и забивает базу данных небольшими запросами. Это также предотвращает использование каких-либо оптимизаций для «значение является одним из тех, что в данном списке»
источник
Альтернативным подходом может быть использование другой таблицы, содержащей значения идентификатора. Эта другая таблица может затем быть внутренне объединена в вашей таблице, чтобы ограничить возвращаемые строки. Это будет иметь главное преимущество в том, что вам не понадобится динамический SQL (в лучшем случае проблематично), и у вас не будет бесконечно длинного предложения IN.
Вы бы обрезали эту другую таблицу, вставили большое количество строк, а затем, возможно, создали бы индекс, чтобы повысить производительность соединения. Это также позволит вам отделить накопление этих строк от извлечения данных, возможно, предоставив вам больше возможностей для настройки производительности.
Обновление : хотя вы можете использовать временную таблицу, я не имел в виду, что вы должны или даже должны. Постоянная таблица, используемая для временных данных, является распространенным решением с достоинствами, помимо описанных здесь.
источник
select
оператора в другой таблице. Список передается как другая таблица, с которой вы работаетеinner join
.То, что предложил Эд Гиннес, действительно повышает производительность, у меня был такой запрос
что я сделал :
Затем внутренний соединяется с основной таблицей:
И производительность значительно улучшилась.
источник
Первый вариант, безусловно, лучший вариант.
Однако, учитывая, что список идентификаторов очень велик , скажем, миллионы, вы должны учитывать размеры блоков, как показано ниже:
Почему вы должны разделить на куски?
Это всегда работало как очарование для меня. Надеюсь, это сработает и для моих коллег-разработчиков :)
источник
Выполнение команды SELECT * FROM MyTable where id in () для таблицы SQL Azure с 500 миллионами записей привело к времени ожидания> 7 минут!
Выполнение этого вместо этого немедленно возвратило результаты:
Используйте соединение.
источник
В большинстве систем баз данных,
IN (val1, val2, …)
а также серииOR
оптимизированы для того же плана.Третий способ - импортировать список значений во временную таблицу и объединить ее, что более эффективно в большинстве систем, если имеется много значений.
Вы можете прочитать эту статью:
источник
Пример 3 был бы худшим из всех, потому что вы попали в базу данных бесчисленное количество раз без видимой причины.
Загрузка данных во временную таблицу и последующее объединение будут самыми быстрыми. После этого IN должен работать немного быстрее, чем группа OR.
источник
Я думаю, что вы имеете в виду SqlServer, но в Oracle у вас есть жесткое ограничение на количество элементов IN, которые вы можете указать: 1000.
источник