SQL Server использует высокий процессор при поиске внутри строк nvarchar

Посмотрите следующий пример. Он показывает, что поиск в строке unicode (nvarchar) почти в восемь раз хуже, чем поиск в строке varchar. И наравне с неявными преобразованиями. Ищете объяснение этого. Или способ поиска в строках nvarchar более эффективно.

use tempdb
create table test
(
    testid int identity primary key,
    v varchar(36),
    nv nvarchar(36),
    filler char(500)
)
go

set nocount on
set statistics time off
insert test (v, nv)
select CAST (newid() as varchar(36)),
    CAST (newid() as nvarchar(36))
go 1000000

set statistics time on
-- search utf8 string
select COUNT(1) from test where v like '%abcd%' option (maxdop 1)
-- CPU time = 906 ms,  elapsed time = 911 ms.

-- search utf8 string using unicode (uses convert_implicit)
select COUNT(1) from test where v like N'%abcd%' option (maxdop 1)
-- CPU time = 6969 ms,  elapsed time = 6970 ms.

-- search unicode string
select COUNT(1) from test where nv like N'%abcd%' option (maxdop 1)
-- CPU time = 6844 ms,  elapsed time = 6911 ms.

Ответ 1

Ищите объяснение для этого.

NVarchar имеет 16 бит, а правила сравнения Unicode намного сложнее, чем ASCII - специальные символы для разных языков, которые поддерживаются в то же время, требуют котировки еще нескольких обработок.

Ответ 2

Я предполагаю, что LIKE реализуется с использованием алгоритма O (n ^ 2) в отличие от алгоритма O (n); вероятно, это должно быть для того, чтобы ведущий % работал. Поскольку строка Юникода в два раза длиннее, это похоже на ваши номера.

Ответ 3

Поиск LIKE %% реализуется как > и <, Теперь больше количества строк, больше времени обработки, чем SQL, не может эффективно использовать статистику для поисковых запросов %%.

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

Эти поисковые запросы лучше всего подходят для полнотекстового поиска или реализованы с использованием FuzzyLookup с хэш-таблицей в памяти, если у вас много ОЗУ и довольно статическая таблица.

НТН

Ответ 4

Я видел подобные проблемы в SQL Server. Был случай, когда я использовал параметризованные запросы, а моим параметром был UTF-8 (по умолчанию в .net), и поле было varchar (а не utf-8). Закончилось преобразование каждого значения индекса в utf-8 только для простого поиска индекса. Это может быть связано с тем, что вся строка может быть переведена на другой набор символов для сравнения. Также для nvarchar "a" будет таким же, как "& aacute"; это означает, что там еще много работы, чтобы выяснить, равны ли 2 строки в юникоде. Кроме того, вы можете использовать полнотекстовую индексацию, хотя я не уверен, что это решает вашу проблему.