Невозможно добавить индекс в сохраняемый вычисляемый столбец, поскольку он «недопустимого типа для использования в качестве ключа» - PullRequest
5 голосов
/ 31 января 2012

У меня есть такая таблица с вычисляемым столбцом:

CREATE TABLE PhoneNumbers
(
    [PhoneNumberID] int identity(1,1) not null primary key clustered,
    [Number] varchar(20), /* Entire number, like (800) 555-5000 */
    [Digits] AS dbo.RegExReplace(Number, '[^0-9]', '') PERSISTED  /* Like 8005555000 */
)

Она создана нормально, а столбец Digits работает отлично, как и ожидалось, НО, похоже, не ведет себя как "PERSISTEDстолбецКогда я делаю запрос с Digits в предложении WHERE, это ОЧЕНЬ медленно.Когда я пытаюсь добавить индекс в столбец «Цифры», я получаю: Column 'Digits' in table 'PhoneNumbers' is of a type that is invalid for use as a key column in an index.

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

RegExReplace - это функция C # CLR, определенная следующим образом:

[SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString RegExReplace(SqlString expression, SqlString pattern, SqlString replace)

Любые идеи о том, как заставить этот столбец Digits действовать как постоянный столбец или разрешить мне добавить индекс?!

Спасибо!

1 Ответ

6 голосов
/ 31 января 2012

Попробуйте CAST:

CREATE TABLE PhoneNumbers
(
    [PhoneNumberID] int identity(1,1) not null primary key clustered,
    [Number] varchar(20), /* Entire number, like (800) 555-5000 */
    [Digits] AS CAST(dbo.RegExReplace(Number, '[^0-9]', '') AS VARCHAR(20)) PERSISTED  /* Like 8005555000 */
)

Я полагаю, что проблема в том, что ваша функция CLR возвращает SqlString, которая в конечном итоге становится nvarchar (4000) или аналогичной - не индексируемой.

Это своего родаизвестной «проблемы» с вычисляемыми столбцами, что тип данных выводится из выражения.В основном проблема со строками и «вспомогательными функциями», которые принимают varchar (max), а также с десятичными операциями, где точность изменяется из-за вычислений.

У меня есть небольшое правило, где я всегда CAST - это делает его явным иизбегает любой двусмысленности.Как правило, столбцы, которые, как известно, являются маленькими, должны быть явно маленькими - varchar (max), похоже, сильно снижает производительность - даже если вы проходите через функцию, которая возвращает varchar (max) и принимает varchar (max), приведите обратно кразмер вы знаете, потому что он будет работать намного лучше.

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