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

Эффективный способ проверки результатов запроса SQL

Я хотел бы написать запрос, который просто возвращает 1 или 0 в зависимости от результатов.

Я думаю использовать этот

IF EXISTS(
      select * from myTable 
      where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0

Это общая предпосылка.

Конечные результаты на самом деле будут гораздо более сложным запросом, взяв один из многих параметров и строку, созданную и выполненную с помощью sp_executesql

Мой вопрос позволяет сказать, что "count" вернет 376986 и займет 4 секунды для вычисления. Является ли использование EX EXISTS прекращением, как только найдет 1 строку, которая удовлетворяет критериям.

Я решаю использовать IF EXISTS или просто запросить @@ROWCOUNT и посмотреть, больше ли оно нуля.

Я действительно пробовал некоторые тесты, и оба они в значительной степени работали с одинаковой скоростью, но через 2 года, когда имеется больше данных, вероятно, использование IF EXISTS будет усилением производительности или нет?

Спасибо

4b9b3361

Ответ 1

IF EXISTS должен быть более эффективным, поскольку он оптимизирован для остановки, как только он найдет первую строку. Так я всегда делал такую ​​проверку, не используя COUNT().

Для сравнения производительности просто убедитесь, что вы честно тестируете, очищая кеши данных и планов выполнения (только не производственный сервер db) перед каждым тестом:

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

Ответ 2

У вас есть указатель на id и дату?

возможно, вы просто хотите:

select top 1  1 from myTable where id=7 and rowInsertDate > '01/01/2009' 

note: это вернет 1, если данные существуют, или ничего в противном случае.

другое редактирование. Это не вернет строку со значением null, если данных нет, но не будет возвращать строки. Больше похоже на нуль в его более образном смысле.

Ответ 3

Это самый быстрый, который я мог бы получить в своих проектах:

SELECT CASE WHEN EXISTS (
  select top 1 1 
  from myTable 
  where id=7 
  and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
) THEN 1 ELSE 0 END AS AnyData

Ответ 4

Если вам не нужны строки 376986 и просто хочу знать, существует ли что-то, то IF EXISTS имеет гораздо больше смысла. Кроме того, еще один полезный бит - попросить индексированный столбец (первичный ключ) вместо *, потому что вам не нужны фактические данные.

Ответ 5

Я просто напишу так:

IF EXISTS(
      SELECT 0 FROM myTable 
      WHERE id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0

Таким образом, вы не возвращаете данные, просто проверяйте условия. Я нахожу эту структуру запросов очень быстрой.

Ответ 6

Конечные результаты будут фактически гораздо более сложный запрос, множество параметров и построенная строка и выполняется с помощью sp_executesql

Я думаю, что вам, по крайней мере, нужен полный синтаксис FROM, JOIN и WHERE, иначе ваш фактический запрос может найти nothiong (например, добавив INNER JOIN, который не был в исходном запросе IF EXISTS, и оказывается не выполненным).

Если вы столкнулись с этой проблемой, вы можете захотеть, чтобы ПК были в какой-то "Таблице удержания пакета", чтобы вы могли просто ссылаться на PK на вторую часть "Представление" вашего запроса.

Что вы планируете делать, если получите 376 986 результатов? Если вы собираетесь показать их пользователю на экране с каким-то пейджингом, то получение результатов в таблице "Столбец для удержания пакета" может помочь в этом (хотя, очевидно, любые добавления/удаления и т.д. К данным udnerlying будет отключать отображаемый экран).

В качестве альтернативы, если вы собираетесь использовать пейджинг, просто используйте TOP/LIMIT/SET ROWCOUNT, чтобы ограничить результаты до первой страницы полной (убедитесь, что у вас есть ORDER BY, чтобы последовательность повторялась), а затем разобраться в том, что для пользователя, когда пользователь нажимает кнопку NEXT-PAGE (мы решаем, что с помощью кнопки NEXT-PAGE, содержащей PK последней отображаемой записи, в порядке сортировки, чтобы следующая страница могла возобновиться с этой точки).

Оптимизатор запросов будет делать разные вещи в зависимости от того, что представляет собой список SELECT, поэтому запрос "IF EXISTS", за которым следуют "SELECT Col1, COl2,... FROM...", может означать, что вы выполняете полный запрос дважды, по-разному, используя разные кэшированные данные и планы запросов, поэтому в целом это может быть более напряженным для вашего сервера и заставляет пользователей ждать дольше, чем просто получить первую страницу /100 строк и т.д.

SQL Server будет кэшировать план запроса для sp_ExecuteSQL, но убедитесь, что вы задаете параметризацию запроса, чтобы по возможности сохранить сохраненный в кэше план

Ответ 7

Прежде всего, вы должны попытаться заглушить базу данных, содержащую столько данных, сколько вы думаете, что вам (или вашим преемникам) придется иметь дело в течение двух лет. Тогда ваши тесты будут намного более продуктивными.

IF EXISTS() будет быстрее, так как движок базы данных должен найти только подходящую запись для ваших критериев. Конечно, он будет быстрее с соответствующими индексами.

Другой намек, не используйте *, так как вам действительно не нужно извлекать столбцы.

IF EXISTS(select 1 from myTable where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE())

... должен (из того, что я прочитал) работать немного быстрее.

Ответ 8

Я думаю, что ответ Алекс Баньолини правильный. Система не позволит мне прокомментировать его ответ (новый acct). Единственное изменение, которое я сделал бы, это изменить второй 1 на id.

Иногда сокращение списка в разделе проекта (список столбцов) позволяет движку db только попадать в индекс, а не в таблицу, тем быстрее. Это, конечно, зависит от вашего механизма БД и структуры индекса/размера. (все даты rowInsertDate должны быть < getDate(), поэтому вы можете пропустить это сравнение)

ВЫБЕРИТЕ СЛУЧАЙ, КОГДА СУЩЕСТВУЕТ ( выберите top 1 id от myTable где id = 7 и rowInsertDate > '01/01/2009 ' ) THEN 1 ELSE 0 END AS AnyData​​p >