"SELECT TOP 1 1" VS "IF EXISTS (ВЫБРАТЬ 1"
У меня есть некоторый .NET-код, который проверяет наличие записи SQL в среднесрочном интервале. Я ищу, чтобы сделать эту проверку как можно "дешевой".
Мне интересно характеристики двух запросов:
IF EXISTS(SELECT 1
FROM BigTable
WHERE SomeColumn = 200)
SELECT 1 AS FOUND
ELSE
SELECT 0 AS FOUND
VS
SELECT TOP 1 1
FROM BigTable
WHERE SomeColumn = 200
Они оба производят аналогичные планы выполнения. Но SELECT TOP 1 1, кажется, выполняется быстрее: меньше запросов для синтаксического анализа и когда запись не найдена, она меньше передает трубку. Я также предполагаю, что он работает быстрее на клиенте, потому что мне просто нужно проверить счетчик записей, а не маршалировать возвращаемое значение IF EXISTS.
Большинство преимуществ производительности незначительны. Но если оба последовательно возвращают один и тот же результат, то почему бы не выбрать немного более быстрый метод?
Является ли "SELECT TOP 1 1" лучшим способом проверить наличие записи в .NET?
(Мы используем .NET 3.5, и я стараюсь избегать LINQ, потому что он не используется в другом месте приложения. У нас также есть некоторые устаревшие приложения VB6, которые мы переносим/переписываем, поэтому им также может понадобиться выполнить это.)
EDIT:
Просто немного подробнее о дизайне. Эта запись является "заголовком". Существует еще одна таблица с дочерними записями, которая будет считана/проанализирована при обнаружении этого заголовка. Отсутствие записи - хорошая вещь: нет работы.
EDIT2: Отсутствие записи, которая удовлетворяет условию, будет происходить чаще. Они происходят спорадическими волнами.
Ответы
Ответ 1
Я бы рекомендовал IF EXISTS(SELECT * ...)
, если это фактически не вызвало проблемы с производительностью. Он выражает намерение запроса гораздо лучше, чем альтернативы.
Я бы избегал COUNT(*)
(как в текущих ответах), если вам действительно не нужно количество строк из таблицы.
Если вам нужна "эффективность" проверки строки из результата, я бы, вероятно, пошел:
select 1 where exists(select * from BigTable where SomeColumn=200)
Что дает тот же результат, что и ваш второй запрос (0 или 1 строка)
Ответ 2
Это то, что вы хотите вместо оператора IF
SELECT ISNULL(
(SELECT TOP 1 1 FROM BigTable where SomeCol = 200), 0);
Ответ 3
Я бы выбрал второй вариант:
SELECT TOP 1 1
FROM BigTable
WHERE SomeColumn = 200
План выполнения более простой и эффективный, даже если номера ввода/вывода и ЦП в основном совпадают.
Ответ 4
Ничего не меняет, существует, даже не оценит выбранную часть вашего утверждения. Итак, используйте тот, который вам нравится.
declare @test table (name varchar(20))
-- comment out inserts for testing.
insert into @test (name) values ('bob the builder')
insert into @test (name) values ('bob the builder')
-- for giggles, put 1/0 here. You'll find that divide by zero error.
select 1 from @test
-- notice that you don't receive a divide by zero error.
-- the bit in the select portion is never executed, ever.
if not exists (select 1/0 from @test) select 'Yay!'
if exists (select 1/0 from @test) select 'Boo!'
На самом деле вы можете использовать их взаимозаменяемо:
... select * ...
... select 1 ...
... select top 1 * ...
... select top 1 1 ...
... select 'John Jacob Jingleheimer Schmidt' ...
Ответ 5
Не уверен насчет SQL Server, но в других базах данных стандартный метод:
SELECT COUNT(*) FROM BigTable where SomeCol = 200;
Фактическая эффективность зависит от ваших показателей и т.д.