Что быстрее (ISNULL (@SKU, '') = '') или (@SKU IS NULL ИЛИ @SKU = '') - PullRequest
0 голосов
/ 13 февраля 2020

В одном случае я использую IF @SKU IS NULL OR @SKU = '', но мой друг говорит, что это займет больше времени по сравнению с IF ISNULL(@SKU, '') = ''. Поэтому вы должны использовать IF ISNULL(@SKU, '') = ''. Но я думаю, что я использую правильно. Поэтому, пожалуйста, предложите мне, какой из них работает быстрее.

Это моя хранимая процедура:

CREATE PROCEDURE USP_GetExistingRefunds  
(  
  @OrderNo VARCHAR(50),  
  @SKU VARCHAR(255),   
  @ProfileID INT   
)  
AS   
BEGIN    
  --IF ISNULL(@SKU, '') = '' --this work faster or 
  IF @SKU IS NULL OR @SKU = '' --this work faster 
  BEGIN 
    SELECT OrderNo, SKU, ISNULL(Quantity, 0) Quantity, ISNULL(Amount, 0) Amount  
    FROM StoreRefundOrder SRO   
    INNER JOIN StoreRefundOrderItem SROI ON SRO.ID = SROI.RefundOrderID   
    WHERE SRO.OrderNo = @OrderNo    
    AND ProfileID = @ProfileID    
  END 
  ELSE
  BEGIN 
    SELECT OrderNo, SKU, ISNULL(SUM(Quantity), 0) Quantity, ISNULL(SUM(Amount), 0) Amount  
    FROM StoreRefundOrder SRO   
    INNER JOIN StoreRefundOrderItem SROI ON SRO.ID = SROI.RefundOrderID   
    WHERE SRO.OrderNo = @OrderNo   
    AND SROI.SKU = @SKU  
    AND ProfileID = @ProfileID   
    GROUP BY OrderNo, SKU   
  END    
END

Ответы [ 4 ]

1 голос
/ 13 февраля 2020

В контексте процедурной партии IF / ELSE

Это не имеет никакого значения. Буквально требуется 0,00 мс, чтобы определить, является ли значение пустым или неизвестным, требуется 0,00 мс, чтобы определить, ISNULL(@SKU, '') = ''. Если есть разница, она, скорее всего, будет измеряться в наносекундах ИМО. Опять же, это в контексте процедурной партии , поскольку оператор оценивается только один раз.

В контексте ФИЛЬТРА (например, ON, WHERE или HAVING CLAUSE)

Здесь разница на самом деле огромна, ее невозможно преуменьшить. Это сложно объяснить с помощью параметров и переменных, поэтому для краткости я покажу вам пример с этими примерами данных:

IF OBJECT_ID('tempdb..#things','U') IS NOT NULL DROP TABLE #things;

SELECT TOP (10000) Txt = SUBSTRING(LEFT(NEWID(),36),1,ABS(CHECKSUM(NEWID())%x.N))
INTO   #things 
FROM       (VALUES(1),(30),(40),(NULL)) AS x(N)
CROSS JOIN sys. all_columns;

UPDATE #things SET Txt = NEWID() WHERE txt = '0';

CREATE NONCLUSTERED INDEX nc_things1 ON #things(Txt);

Следующие запросы найдут строки, которые содержат или не содержат пробелы или nulls

-- Finding things that are blank or NULL
SELECT t.Txt
FROM   #things AS t
WHERE  t.Txt IS NULL OR t.Txt = '';

-- Finding things that are NOT blank or NULL
SELECT t.Txt
FROM   #things AS t
WHERE  NOT(t.Txt IS NULL OR t.Txt = '');

SELECT t.Txt
FROM   #things AS t
WHERE  t.Txt > '';

-- Finding things that are blank or NULL
SELECT t.Txt
FROM   #things AS t
WHERE  ISNULL(t.Txt,'') = '';

-- Finding things that are NOT blank or NULL
SELECT t.Txt
FROM   #things AS t
WHERE  ISNULL(t.Txt,'') <> '';

Первые три запроса SARGable, последние два не из-за ISNULL. Хотя есть индекс, чтобы помочь мне, ISNULL делает его здесь бесполезным. Разница заключается в том, чтобы попросить кого-нибудь поискать в телефонной книге всех, чье имя начинается с с «А», и найти всех, чье имя заканчивается на «А».

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

ПЛАНЫ ИСПОЛНЕНИЯ:

enter image description here

Обратите внимание, что этот последний WHERE t.Txt > '' также будет работать. Любое ненулевое текстовое значение равно > '', и если t.Txt было НЕДЕЙСТВИТЕЛЬНО, оно также оценивается как ложное. Я включил это, потому что это выражение работает для отфильтрованных индексов. Единственная загвоздка в том, что вы не можете использовать его в текстовом поле, где неявное преобразование может преобразовать это в число 0 или меньше. Обратите внимание на следующие запросы:

IF '' =   0  PRINT 'True' ELSE PRINT 'False'; -- Returns True
IF '' =  '0' PRINT 'True' ELSE PRINT 'False'; -- Returns False
IF '' >  -1  PRINT 'True' ELSE PRINT 'False'; -- Returns True
IF '' > '-1' PRINT 'True' ELSE PRINT 'False'; -- Returns False
0 голосов
/ 13 февраля 2020

Что быстрее (ISNULL(@SKU, '') = '') или (@SKU IS NULL OR @SKU = '')

Это действительно не имеет значения в этом случае. Если вы сравниваете со столбцом, то предпочтительным будет (SKU IS NULL OR SKU = ''), поскольку он может использовать индекс, но любая разница для одного сравнения с переменной будет порядка микросекунд и будет меньше времени выполнения операторов SELECT.

Чтобы упростить оператор IF, я, вероятно, в любом случае инвертирую его, как показано ниже

  IF @SKU <> '' --Not null or empty string
  BEGIN 
    SELECT OrderNo, SKU, ISNULL(SUM(Quantity), 0) Quantity, ISNULL(SUM(Amount), 0) Amount  
    FROM StoreRefundOrder SRO   
    INNER JOIN StoreRefundOrderItem SROI ON SRO.ID = SROI.RefundOrderID   
    WHERE SRO.OrderNo = @OrderNo   
    AND SROI.SKU = @SKU  
    AND ProfileID = @ProfileID   
    GROUP BY OrderNo, SKU  
  END 
  ELSE
  BEGIN 
     SELECT OrderNo, SKU, ISNULL(Quantity, 0) Quantity, ISNULL(Amount, 0) Amount  
    FROM StoreRefundOrder SRO   
    INNER JOIN StoreRefundOrderItem SROI ON SRO.ID = SROI.RefundOrderID   
    WHERE SRO.OrderNo = @OrderNo    
    AND ProfileID = @ProfileID  
  END  
0 голосов
/ 13 февраля 2020

Немного долго для комментария.

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

В верхней части блока кода добавьте эту команду :

SET STATISTICS TIME, IO ON;

Вы можете использовать TIME или IO, но я почти всегда хочу видеть оба, поэтому я всегда включаю их обоих одновременно.

вывод этого дополнения будет отображаться в окне «Сообщения» после выполнения запроса или запросов и даст вам реальную информацию о том, какой метод работает быстрее или вызывает меньшую нагрузку на ядро ​​сервера SQL.

Вы захотите запустить несколько тестов с каждой опцией. Теплый кеш / холодный кеш, особенно, но несколько итераций лучше всего подходят для получения усредненных результатов или исключения результатов.

Я странный, поэтому я всегда закрываю свой блок кода с помощью:

SET STATISTICS TIME, IO OFF;

Но, строго говоря, это не нужно. У меня есть кое-что о том, как сбросить все, что я изменяю, просто чтобы избежать любой возможности забыть сбросить что-то, что будет иметь значение.

У Кендры Литтла есть информативное сообщение в блоге об использовании STATISTICS.

0 голосов
/ 13 февраля 2020

IF @SKU IS NULL OR @SKU ='' проверяет нулевое и пустое оба. Во втором случае if Isnull(@sku,'') вы проверяете ноль и присваиваете '' нулевое значение. Оба это разные случаи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...