Я знаю, что эта тема была избита до смерти, но кажется, что многие статьи в Интернете часто ищут самый элегантный способ, а не самый эффективный способ его решения. Вот проблема. Мы создаем приложение, в котором один из общих запросов к базе данных будет включать манипуляции (SELECTs и UPDATE) на основе списка пользователей, предоставленного пользователем. Ожидается, что в таблице, которая будет содержаться сотни тысяч строк, и предоставленные пользователем списки идентификаторов могут быть потенциально неограниченными, bust они будут наиболее вероятными с точки зрения десятков или сотен (мы можем ограничить его по соображениям производительности позже).
Если мое понимание того, как работают базы данных в целом, является правильным, наиболее эффективным является просто использовать конструкцию WHERE ID IN (1, 2, 3, 4, 5, ...)
и строить запросы динамически. Ядро проблемы состоит в том, что входные списки идентификаторов будут действительно произвольными, и поэтому, независимо от того, насколько умны базы данных или насколько их мы умело используем, у нас всегда есть случайное подмножество целых чисел, и поэтому в конечном итоге каждый подход должен внутренне сводятся к чему-то вроде WHERE ID IN (1, 2, 3, 4, 5, ...)
в любом случае.
Можно найти множество подходов по всему Интернету. Например, один включает объявление переменной таблицы, передачу списка идентификаторов в процедуру хранилища в виде строки с разделителями-запятыми, разделение ее в процедуре хранилища, вставку идентификаторов в переменную таблицы и присоединение к ней основной таблицы, то есть нечто вроде это:
-- 1. Temporary table for ID’s:
DECLARE @IDS TABLE (ID int);
-- 2. Split the given string of ID’s, and each ID to @IDS.
-- Omitted for brevity.
-- 3. Join the main table to @ID’s:
SELECT MyTable.ID, MyTable.SomeColumn
FROM MyTable INNER JOIN @IDS ON MyTable.ID = @IDS.ID;
Устраняя проблемы с манипуляциями со строками, я думаю, что в основном это происходит в том, что на третьем этапе SQL Server говорит: "Спасибо, это хорошо, но мне просто нужен список идентификаторов", и это сканирует переменную таблицы @IDS
, а затем n ищет в MyTable
, где n - количество идентификаторов. Я провела некоторые элементарные оценки производительности и проверила план запросов, и кажется, что это то, что происходит. Таким образом, переменная таблицы, конкатенация и разделение строк и все дополнительные INSERT - ни для чего.
Правильно ли я? Или я что-то упускаю? Действительно ли какой-то умный и эффективный способ? В основном, то, что я говорю, заключается в том, что SQL Server должен делать n указателей, независимо от того, что и как сформулировать запрос, поскольку WHERE ID IN (1, 2, 3, 4, 5, ...)
является самым простым способом его запросить.