Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Оптимизация запроса  [new]
BKV
Member

Откуда:
Сообщений: 4
Всем добрый день!
Нужен совет по правильному построению таблицы и запроса для следующей ситуации:
Есть БОЛЬШАЯ таблица (Сотни миллионов записей) - tblMain.
Структура:
CREATE TABLE [tblMain](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[GId] [uniqueidentifier] NOT NULL,
	[Name] [nvarchar](50) NOT NULL,
	[TimeEnter] [datetime] NOT NULL,
	[Id_RoleSet] [int] NOT NULL,
	[Gid_LineSet] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_DOC] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)
CREATE NONCLUSTERED INDEX [IX_tblMain_Gid_LineSet] ON [tblMain] 
(
	[Gid_LineSet] ASC,
	[Id_RoleSet] ASC,
	[TimeEnter] DESC
)


При выборке из этой таблицы вида
 Select TOP 10000 * from tblMain where Id_RoleSet = 5 and Gid_LineSet = 'A8BC87A7-0C84-4F2B-AE2D-EC7E6310FE98'
 Order By TimeEnter Desc

проблем нет, используется индекс IX_tblMain_Gid_LineSet.

Но когда надо выбрать из таблицы первые N строк, отсортированные по полю TimeEnter, где [Id_RoleSet]и [Gid_LineSet] входят в выборку ~ 200-300 строк.
Что-то вроде:
 Select TOP 10000 * from tblMain where Id_RoleSet in (Select Gid from tableGid) and Gid_LineSet in (Select id from tableGid)
 Order By TimeEnter Desc

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

Как правильно оптимизировать структуру таблицы, индексы и запрос для подобной задачи?
Спасибо.
19 мар 13, 01:23    [14065074]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
А у вас в реальности запросы, как в примерах - звездные?

Здесь композитник работать не будет, нужно либо 3 отдельных индекса на каждое из полей, либо TimeEnter всунуть куда-либо, типа (Id_RoleSet, TimeEnter) + (Gid_LineSet).

Ну и такие условия
where Id_RoleSet in (Select Gid from tableGid) and Gid_LineSet in (Select id from tableGid)
, если я правильно понимаю, должны скорее внешними ключами обеспечиваться, не?
19 мар 13, 01:34    [14065107]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
BKV,

Если убрать TOP 10000, то сколько будет выбрано строк? Именно такой объем должен быть сначала прочитан используя Index Seek + Lookup чтобы задействовать индекс, таким образом сервер решает что просканировать кластер будет дешевле.
Еще возможно ошибка в кардиналити. Планы покажите, желательно актуальные и виде .sqlplan файлов.
19 мар 13, 01:36    [14065113]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Ennor Tiegael
Здесь композитник работать не будет, нужно либо 3 отдельных индекса на каждое из полей,
А чем это поможет?
Ennor Tiegael
либо TimeEnter всунуть куда-либо, типа (Id_RoleSet, TimeEnter) + (Gid_LineSet).
Или это?
19 мар 13, 01:41    [14065119]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
BKV
Member

Откуда:
Сообщений: 4
Mind
BKV,
Если убрать TOP 10000, то сколько будет выбрано строк? Именно такой объем должен быть сначала прочитан используя Index Seek + Lookup чтобы задействовать индекс, таким образом сервер решает что просканировать кластер будет дешевле.
Еще возможно ошибка в кардиналити. Планы покажите, желательно актуальные и виде .sqlplan файлов.


Если убрать TOP 10000 - то выборка будет большой, несколько миллионов.
Вопрос есть ли способ как-то оптимизировать выполнение подобной выборки?
19 мар 13, 02:20    [14065156]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
BKV,

where Id_RoleSet in (Select Gid from tableGid) and Gid_LineSet in (Select id from tableGid)
А вот это условие вообще хотя бы правильно? Какой тут был смысл?
19 мар 13, 03:27    [14065195]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
aleks2
Guest
BKV
Что-то вроде:
 Select TOP 10000 * from tblMain where Id_RoleSet in (Select Gid from tableGid) and Gid_LineSet in (Select id from tableGid)
 Order By TimeEnter Desc

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

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


Заменить (Select Gid from tableGid) на табличную переменную
declare @G table  (Gid primary key clustered)

insert @G Select distinct Gid from tableGid

Select TOP 10000 * from tblMain where Id_RoleSet in (Select Gid from @G) and ...

со вторым in поступить аналогично.

Лично я бы ваще пошел еще дальше
declare @GI table  (Gid, id, primary key clustered(Gid, id))

insert @GI 
select Gid, id
from
(Select distinct Gid from tableGid) x
cross join
(Select distinct id from tableGid) y

Select TOP 10000 t.* from tblMain t inner join @GI gi on t.Id_RoleSet=gi.Gid and ...
19 мар 13, 07:04    [14065246]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить