Будет ли Microsoft SQL Server эффективно обрабатывать непостоянный вычисляемый столбец? - PullRequest
4 голосов
/ 13 августа 2010

Мне трудно сформулировать этот вопрос таким образом, чтобы результаты не были сохранены для постоянных, индексированных вычисляемых столбцов.

Мой вопрос: есть ли у меня таблица, такая как:

CREATE TABLE Customers (
    ID int,
    Name nvarchar(50),
    Balance money,
    HasBalance AS CONVERT(bit, CASE WHEN Balance > 0 THEN 1 ELSE 0 END)
)

Если предположить, что есть индекс по Балансу, обработчик запросов SQL эффективно обработает запрос, такой как:

SELECT ID, Name, Balance
FROM Customers
WHERE HasBalance = 1

По сути ли это "встроит" выражение вычисляемого столбца, как если бы яуказывал регистр непосредственно в запросе?

А как насчет того, чтобы выражение вычисляемого столбца находилось в пользовательской функции без привязки к схеме?

EDIT

Мой пример не был удачным, поскольку, как уже отмечалось, столбец HasBalance не будет иметь очень хорошего распределения данных.Но на мгновение игнорируя эффективность самого индекса, обработчик запросов будет в основном обрабатывать вышеуказанный запрос, как показано ниже, при выборе индекса и выборе плана выполнения?

SELECT ID, Name, Balance
FROM Customers
WHERE Balance > 0

1 Ответ

4 голосов
/ 13 августа 2010

Это зависит от распределения данных, сейчас у вас есть только 2 возможных значения 1 и 0 .... поэтому, если у вас 99% данных не одно значение, ваша селективность будет очень плохой, тогда она должна отсканировать весь индекс, чтобы найти все положительные или отрицательные значения

Изменить ..... Вот что происходит, вы получаете сканирование таблицы

CREATE TABLE Customers (
    ID int,
    Name nvarchar(50),
    Balance money,
    HasBalance AS CONVERT(bit, CASE WHEN Balance > 0 THEN 1 ELSE 0 END)
)


insert Customers values(1,'d',100)
insert Customers values(2,'d',-2)
insert Customers values(3,'d',-4)
insert Customers values(4,'d',3)
insert Customers values(5,'d',5)

create index ix_test on Customers(Balance)


SELECT ID, Name, Balance
FROM Customers
WHERE HasBalance = 0

set showplan_text on

| - Сканирование таблицы (ОБЪЕКТ: ([master]. [Dbo]. [Customers]), ГДЕ: (ПРЕОБРАЗОВАТЬ (бит, СЛУЧАЙ КОГДА [master]. [Dbo]. [Клиенты]. [Баланс]> (0,0000 долл. США) THEN (1) ELSE (0) END, 0) = [@ 1]))

И посмотрите на это

SELECT Balance
FROM Customers
WHERE HasBalance = 0

- Сканирование индекса (OBJECT: ([master]. [Dbo]. [Customers]. [Ix_test]), WHERE: (CONVERT (бит, ПРИМЕР, КОГДА [master]. [Dbo]. [Customers]. [Balance]> (0,0000 долл. США) THEN (1) ELSE (0) END, 0) = [@ 1]))

SELECT Balance
FROM Customers
WHERE Balance > 0

| - Поиск индекса (OBJECT: ([master]. [Dbo]. [Customers]. [Ix_test]), SEEK: ([master]. [Dbo]. [Customers]. [Баланс]> CONVERT_IMPLICIT (деньги, [@ 1], 0)) ЗАКАЗАТЬ ВПЕРЕД)

...