Быстрее проверить, если длина = 0, чем сравнить его с пустой строкой? - PullRequest
26 голосов
/ 28 июля 2010

Я слышал, что в некоторых языках программирования быстрее проверить, равна ли длина строки 0, чем проверить, является ли содержимое "".Это также верно для T-SQL?

Пример:

SELECT user_id FROM users WHERE LEN(user_email) = 0

против

SELECT user_id FROM users WHERE user_email = ''

Ответы [ 3 ]

27 голосов
/ 28 июля 2010

Редактировать Вы обновили свой вопрос, так как я впервые посмотрел на него. В этом примере я бы сказал, что вы обязательно должны всегда использовать

SELECT user_id FROM users WHERE user_email = ''

Не

SELECT user_id FROM users WHERE LEN(user_email) = 0

Первый позволит использовать индекс. В качестве оптимизации производительности это превзойдет некоторую строковую микрооптимизацию каждый раз! Чтобы увидеть это

SELECT * into #temp FROM [master].[dbo].[spt_values]

CREATE CLUSTERED INDEX ix ON #temp([name],[number])

SELECT [number] FROM #temp WHERE [name] = ''

SELECT [number] FROM #temp WHERE LEN([name]) = 0

Планы выполнения

Execution Plans

Оригинальный ответ

В приведенном ниже коде (SQL Server 2008 - я «позаимствовал» временную структуру из ответа @ 8kb здесь ) я получил небольшое преимущество для проверки длины, а не содержимого ниже, когда содержалось @stringToTest строка. Они были равны по времени, когда NULL. Я, вероятно, недостаточно проверял, чтобы сделать какие-то твердые выводы.

В типичном плане выполнения я бы предположил, что разница будет незначительной, и если вы будете проводить такое большое сравнение строк в TSQL, что это, вероятно, будет иметь какое-то существенное значение, вам, вероятно, следует использовать другой язык для него. 1030 *

DECLARE @date DATETIME2
DECLARE @testContents INT
DECLARE @testLength INT

SET @testContents = 0
SET @testLength = 0


DECLARE 
  @count INT,
  @value INT,
  @stringToTest varchar(100)


set @stringToTest = 'jasdsdjkfhjskdhdfkjshdfkjsdehdjfk'
SET @count = 1

WHILE @count < 10000000
BEGIN

  SET @date = GETDATE()
  SELECT @value = CASE WHEN @stringToTest = '' then 1 else 0 end
  SET @testContents = @testContents + DATEDIFF(MICROSECOND, @date, GETDATE())

  SET @date = GETDATE()
  SELECT @value = CASE WHEN len(@stringToTest) = 0 then 1 else 0 end
  SET @testLength = @testLength + DATEDIFF(MICROSECOND, @date, GETDATE())

  SET @count = @count + 1
END

SELECT 
  @testContents / 1000000. AS Seconds_TestingContents, 
  @testLength / 1000000. AS Seconds_TestingLength
7 голосов
/ 28 июля 2010

Я бы с осторожностью использовал LEN в предложении WHERE, так как это может привести к сканированию таблицы или индекса.

Также обратите внимание, что если поле NULL способны, то LEN(NULL) = NULL,поэтому вам необходимо определить поведение, например:

-- Cost .33
select * from [table]
where itemid = ''

-- Cost .53
select * from [table]
where len(itemid) = 0

-- `NULL`able source field (and assuming we treat NULL and '' as the same)
select * from [table]
where len(itemid) = 0 or itemid is NULL
5 голосов
/ 28 июля 2010

Я только что протестировал его в очень ограниченном сценарии, и план выполнения очень даже немного предпочтителен при сравнении с пустой строкой. (От 49% до 51%). Это работает с данными в памяти, хотя, вероятно, будет отличаться, если сравнивать с данными из таблицы.

DECLARE @testString nvarchar(max)
SET @testString = ''

SELECT
    1
WHERE
    @testString = ''

SELECT
    1
WHERE
    LEN(@testString) = 0

Редактировать: это с SQL Server 2005.

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