SQL Server – индекс вычисляемого столбца?
-
19-09-2019 - |
Вопрос
Я присоединяюсь к таблице десятки разных раз, и каждый раз я присоединяюсь (или фильтрую) на основе результатов ПОДСТРОКИ одного из столбцов (это строка, но дополненная нулями слева, и я не меня не волнуют последние четыре цифры).В результате, хотя этот столбец проиндексирован и мой запрос будет использовать этот индекс, он выполняет сканирование таблицы, поскольку сама SUBSTRING не индексируется, поэтому SQL Server должен вычислять ее для каждой строки перед ее объединением.
Я ищу любые идеи о том, как ускорить этот процесс.В настоящее время в таблице есть представление (это «SELECT * FROM», просто чтобы дать таблице понятное имя), и я подумываю о добавлении столбца в вычисляемое представление, а затем его индексировании.Я открыт для других предложений, есть какие-нибудь мысли?
БОЛЕЕ ДЕТАЛЬНО:Я должен был поделиться этим с самого начала.Таблица получает репликацию от нашей системы выставления счетов, поэтому редактирование базовой таблицы для добавления вычисляемого столбца невозможно.Любой вычисляемый столбец необходимо будет добавить в представление таблицы.Кроме того, ведущие нули не всегда являются ведущими нулями — иногда это другие данные, которые меня не интересуют.Полагаю, настоящий вопрос заключается в следующем: "Как я могу присоединиться к данным в середине столбца VARCHAR, одновременно используя индекс?Полнотекстовый поиск?"
Уточняю свой примерЯ упрощаю, но, по сути, скажем, я пытаюсь найти значения в столбце со следующими значениями:
00000012345MoreStuff
00000012345Whatever
19834212345
Houses12345837443GGD
00000023456MoreStuff
Меня интересуют строки, в которых SUBSTRING(7,5)="12345", поэтому мне нужны строки 1–4, но не строка 5.Я предлагаю добавить столбец в мое представление «SELECT *», в котором есть эта подстрока, а затем индексировать его на основе этого.Имеет ли это больше смысла?
Решение
Предполагая, что у вас есть поля в этом формате:
00Data0007
000000Data0011
0000Data0015
, вы можете сделать следующее:
Создайте вычисляемый столбец:
ndata AS RIGHT(REVERSE(data), LEN(data) - 4)
Это преобразует ваши столбцы в следующее:
ataD00 ataD000000 ataD0000
Создайте индекс для этого столбца
Выполните этот запрос для поиска строки
Data
:SELECT * FROM mytable WHERE ndata LIKE N'ataD%' AND SUBSTRING(ndata, LEN(N'ataD') + 1, LEN(ndata)) = REPLICATE('0', LEN(ndata) - LEN('ataD'))
Первое условие будет использовать индекс для грубой фильтрации.
Второй будет следить за тем, чтобы все ведущие символы (которые стали конечными символами в вычисляемом столбце) были не чем иным, как нулями.
Подробную информацию о производительности смотрите в этой записи в моем блоге:
Обновлять
Если вам просто нужен индекс на SUBSTRING
без изменения схемы можно создать представление.
CREATE VIEW v_substring75
WITH SCHEMABINDING
AS
SELECT s.id, s.data, SUBSTRING(data, 7, 5) AS substring75
FROM mytable
CREATE UNIQUE CLUSTERED INDEX UX_substring75_substring_id ON (substring75, id)
SELECT id, data
FROM v_substring75
WHERE substring75 = '12345'
Другие советы
Добавить вычисляемый столбец в вашу таблицу и создайте индекс для этого столбца.
ALTER TABLE MyTable
Add Column CodeHead As LEFT(Code,Len(Code)-4)
Затем создайте индекс по этому вопросу.
CREATE INDEX CodeHeadIdx ON MyTable.CodeHead
Можете ли вы перефразировать критерии вашего фильтра в виде утверждения LIKE «что-то%»?(Это применимо к индексу)
Измените столбец на два столбца — данные, к которым вы присоединяетесь, и дополнительные 4 символа.Как вы уже видели, использование частей столбца замедляет работу.