2016-06-12 3 views
1

У меня есть две аналогичные таблицы,SQL план выполнения

CREATE TABLE [dbo].[StockPrices] (
    [Id]  INT    IDENTITY (1, 1) NOT NULL, 
    [CompanyId] INT    NOT NULL, 
    [Date]  DATETIME  NOT NULL, 
    [Open]  DECIMAL (18, 2) NOT NULL, 
    [Close]  DECIMAL (18, 2) NOT NULL, 
    [Low]  DECIMAL (18, 2) NOT NULL, 
    [High]  DECIMAL (18, 2) NOT NULL, 
    [Volume] INT    NOT NULL, 
    CONSTRAINT [PK_dbo.StockPrices] PRIMARY KEY NONCLUSTERED ([Id] ASC), 
    CONSTRAINT [FK_dbo.StockPrices_dbo.Companies_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Companies] ([Id]) ON DELETE CASCADE 
); 

GO 
CREATE CLUSTERED INDEX [IX_CompanyId] ON [dbo].[StockPrices]([CompanyId] ASC); 

GO 
CREATE NONCLUSTERED INDEX [IX_Date] ON [dbo].[StockPrices]([Date] ASC); 

и

CREATE TABLE [dbo].[News] (
    [Id]    INT   IDENTITY (1, 1) NOT NULL, 
    [NewsProviderId] INT   NOT NULL, 
    [CompanyId]  INT   NOT NULL, 
    [Date]   DATETIME  NOT NULL, 
    [Title]   NVARCHAR (128) NOT NULL, 
    [Description] NVARCHAR (256) NOT NULL, 
    [Url]   NVARCHAR (256) NOT NULL, 
    CONSTRAINT [PK_dbo.News] PRIMARY KEY NONCLUSTERED ([Id] ASC), 
    CONSTRAINT [FK_dbo.News_dbo.Companies_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Companies] ([Id]) ON DELETE CASCADE 
); 
GO 

CREATE CLUSTERED INDEX [IX_CompanyId] ON [dbo].[News]([CompanyId] ASC); 
GO 

CREATE NONCLUSTERED INDEX [IX_Date] ON [dbo].[News]([Date] ASC); 
GO 

и две аналогичные запросы

select * 
from news 
where companyid = 1 
    and date >= '01/01/2010' 
    and date <= '01/31/2010' 
order by date; 

select * 
from stockprices 
where companyid = 1 
    and date >= '01/01/2010' 
    and date <= '01/31/2010' 
order by date; 

и я получаю две совершенно разные фактическое исполнение планов

Query1: По отношению к партии: 86%

SELECT (COST 0%) < - Вложенные циклы (Inneer Join) (Стоимость 0%) < - Index Seek (NONCLUSTERED) [Новости] [IX_Date]. (Стоимость 1%) < - Key Lookup (кластерная) [Новости] [IX_CompanyId] (Стоимость 99%)

Запрос 2:. по отношению к партии: 14%

SELECT (Cost0%) < - Sort (Стоимость 33%) < - кластерного индекса сканирования (кластерной) [StockPrices] IX_CompanyId

Я не знаю, почему? Вы можете что-то посоветовать?

ответ

3

Первый использует поиск по неклассифицированному кластерному индексу в порядке дат и ключевому поиску, чтобы получить оставшиеся столбцы для строк, соответствующих companyid = 1.

Второй выполняет сканирование по индексу покрытия, а затем сортирует отфильтрованный результат.

Это решение, основанное на затратах, в зависимости от того, какая доля таблицы оценивается, и ширины двух индексов (some example calculations here).

Ключевой поиск дорог, поскольку каждый из них требует выполнения кластерного индекса, чтобы найти нужную страницу и строку. Это означает, что для каждой строки необходимо найти несколько страниц, найденных по некластеризованному индексу (столько страниц, сколько глубина кластерного индекса). Более того, кластеризованная индексная страница, найденная для одной строки, может, скорее всего, не быть скоррелированной на странице для следующей строки, что приведет к множеству случайных значений ввода-вывода.

В результате переломная точка перед тем, как план переключается на сканирование индекса, может быть очень низкой частью таблицы. Тот факт, что индекс без покрытия может избежать сортировки в этом случае, может сделать точку опрокидывания немного выше, чем в противном случае.

Посмотрите на оценочные строки по каждому из них. Также считайте, что таблица News содержит различные строковые столбцы и, вероятно, подходит меньше строк на кластерной странице индекса, чем числовые значения в таблице StockPrices, поэтому полное сканирование с кластерным индексом на News может быть относительно более дорогостоящим и вызвать более высокую точку опрокидывания.

Смежные вопросы