Я услышал, что на некоторых языках программирования это быстрее, чтобы проверить, ли длина строки 0
, чем проверить, ли содержание ""
. Это также верно для T-SQL?
Образец:
SELECT user_id FROM users WHERE LEN(user_email) = 0
по сравнению с.
SELECT user_id FROM users WHERE user_email = ''
Редактировать Вы обновили свой вопрос с тех пор, как я впервые посмотрел на него. В этом примере я бы сказал, что вам обязательно всегда следует использовать
SELECT user_id FROM users WHERE user_email = ''
Not
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
Планы выполнения
Исходный ответ
В приведенном ниже коде (SQL Server 2008 - я «позаимствовал» структуру синхронизации из @ 8kb, ответ здесь ) я получил небольшое преимущество для проверка длины, а не содержимого ниже, когда @stringToTest
содержит строку. При NULL они были равными таймингами. Однако я, вероятно, не проверил достаточно, чтобы сделать какие-либо твердые выводы.
В типичном плане выполнения, я бы предположил, что разница будет незначительной, и если вы проводите такое частое сравнение строк в TSQL, которое, вероятно, будет иметь какое-либо существенное значение, вам, вероятно, следует использовать для этого другой язык.
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
Я только что протестировал его в очень ограниченном сценарии и выполнении plan даже немного предпочитает сравнивать его с пустой строкой. (От 49% до 51%). Это работает с данными в памяти, поэтому, вероятно, все будет по-другому при сравнении с данными из таблицы.
DECLARE @testString nvarchar(max)
SET @testString = ''
SELECT
1
WHERE
@testString = ''
SELECT
1
WHERE
LEN(@testString) = 0
Изменить: это с SQL Server 2005.
Я был бы осторожен при использовании 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