Подтвердить что ты не робот

"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: Отсутствие записи, которая удовлетворяет условию, будет происходить чаще. Они происходят спорадическими волнами.

4b9b3361

Ответ 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;

Фактическая эффективность зависит от ваших показателей и т.д.