powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / В представлении оптимизатор не видит индексов
1 сообщений из 26, страница 2 из 2
В представлении оптимизатор не видит индексов
    #38229553
Фотография SomewhereSomehow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_ч_,

Теперь стало понятнее в чем дело.
Дело не в представлении, а в том, что вы указываете разные порядки сортировки, при том, что к сожалению, свойство сортировки имеет ограничение на распространение на нижние операторы.
Попробуйте выполнить запрос, без view:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT TOP 50 * FROM
(
	SELECT ID
			,summ
			,name
			,processed
	FROM test_b WITH (NOLOCK)
	UNION ALL
	SELECT ID
			,summ
			,name
			,processed
	FROM test_a WITH (NOLOCK)
) as test_all
ORDER BY processed asc


Вы увидите точно такой же план:


Если обратите внимание, то сканирование не упорядоченное, а сортировка по двум полям, одно то, которое вы указали явно - processed, другое - ключ кластерного, которое, вы нигде не указывали.

Откуда требование ко второму ключу.
В этом виноват оператор Merge Join (Concatenation), который требует чтобы строки к нему поступали в отсортированном порядке. А т.к. выбираются все строки, то чем делать сортировку по многим столбцам, проще сделать сортировку по одному уникальному столбцу кластерного индекса и первичного ключа.

В одиночном запросе
Код: sql
1.
SELECT TOP 50 * FROM test_a ORDER BY processed


Merge - нет, требований к сортировке по ID нет.

Если сделать индекс покрывающим (в данном случае, я просто поменяю запрос, для простоты):
Код: sql
1.
SELECT TOP 50 processed from dbo.test_all ORDER BY processed ASC


То план будет:


Т.е. сортировка обеспечивается сканированием в обратном порядке.
Теперь, добавим поле name в запрос:
Код: sql
1.
SELECT TOP 50 processed,name from dbo.test_all ORDER BY processed ASC


Снова план:


Но на этот раз, участвует колонка name.
Если добавить ее в индекс как ключевую колонку, чтобы обеспечить сортировку:
Код: sql
1.
2.
3.
create nonclustered index [idx_test_a_processed_name] on test_a(processed DESC, name desc);
create nonclustered index [idx_test_b_processed_name] on test_b(processed DESC, name desc);
SELECT TOP 50 processed, name from dbo.test_all ORDER BY processed ASC


План:


Код: sql
1.
drop index test_a.[idx_test_a_processed_name], test_b.[idx_test_b_processed_name];



В чем состоит ограничение.
Хотя нигде явно требования по сортировке в порядке возрастания колонки ID asc не указано, оптимизатор, виду ограничения распространения свойств сортировки не рассматривает вариант ID desc при вычислении свойств сортировки сканирования.
На эту тему есть item MS Connect заведенный Steve Kass.
Query optimizer misses optimal ORDERED BACKWARD plan unless query includes ORDER BY.
Который, к сожалению, закрыт как Closed as Won't Fix .
Объяснения от MSThis is due to a known limitation of sort property propagation. I would like to address this when Yukon SP3 work starts in earnest, but we'll see, since it's significant effort.
Но воз и ныне там =)

Что можно сделать
1. Явно определить порядок сортировки ключа кластерного, что приведет оптимизатор к backward scan и избавлению от сортировки:
Код: sql
1.
SELECT TOP 50 * from dbo.test_all ORDER BY processed ASC, ID desc



2. Если реальные данные позволяют, сделать индекс уникальным, тогда у оптимизатора отпадет необходимость включать в сортировку ключ кластерного чтобы обеспечить сортировку строк.
Код: sql
1.
2.
3.
4.
5.
6.
update test_a set processed = dateadd(s,id,processed); --to unify sample data
create unique nonclustered index [idx_test_a_processed] on test_a(processed DESC) with drop_existing;
create unique nonclustered index [idx_test_b_processed] on test_b(processed DESC) with drop_existing;
go
SELECT TOP 50 * from dbo.test_all ORDER BY processed ASC
go



3. Добавить в некластерный ключ кластерного с явной сортировкой
Код: sql
1.
2.
3.
4.
5.
create nonclustered index [idx_test_a_processed] on test_a(processed DESC, id desc) with drop_existing;
create nonclustered index [idx_test_b_processed] on test_b(processed DESC, id desc) with drop_existing;
go
SELECT TOP 50 * from dbo.test_all ORDER BY processed ASC
go



Все три приводят к плану:


В целом, досадное упущение оптимизатора. Я смотрю вы тоже завели Item на коннект. Публикуйте его сюда, пусть люди голосуют, авось пофиксят =)
...
Рейтинг: 0 / 0
1 сообщений из 26, страница 2 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / В представлении оптимизатор не видит индексов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]