Настройка производительности при чтении огромного стола - PullRequest
0 голосов
/ 28 марта 2011

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

Итак, я создал тестовую среду с этимопределение таблицы:

CREATE TABLE [dbo].[Test](
[Dim1ID] [nvarchar](20) NOT NULL,
[Dim2ID] [nvarchar](20) NOT NULL,
[Dim3ID] [nvarchar](4) NOT NULL,
[Dim4ID] [smalldatetime] NOT NULL,
[Dim5ID] [nvarchar](20) NOT NULL,
[Dim6ID] [nvarchar](4) NOT NULL,
[Dim7ID] [nvarchar](4) NOT NULL,
[Dim8ID] [nvarchar](4) NOT NULL,
[Dim9ID] [nvarchar](4) NOT NULL,
[Dim10ID] [nvarchar](4) NOT NULL,
[Dim11ID] [nvarchar](20) NOT NULL,
[Value] [decimal](21, 6) NOT NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
[Dim1ID] ASC,
[Dim2ID] ASC,
[Dim3ID] ASC,
[Dim4ID] ASC,
[Dim5ID] ASC,
[Dim6ID] ASC,
[Dim7ID] ASC,
[Dim8ID] ASC,
[Dim9ID] ASC,
[Dim10ID] ASC,
[Dim11ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] 

Эта таблица является таблицей фактов архитектуры схемы Star (факт / измерения).Как видите, у меня есть кластеризованный индекс по всем столбцам, кроме столбца «Значение».

Я заполнил эти данные ок.10 000 000 строк для целей тестирования.Фрагментация в настоящее время составляет 0,01%.

Я хотел бы повысить производительность при чтении набора строк из этой таблицы с помощью этого запроса:

DECLARE @Dim1ID nvarchar(20) = 'C1'
DECLARE @Dim9ID nvarchar(4) = 'VRT1'
DECLARE @Dim10ID nvarchar(4) = 'S1'
DECLARE @Dim6ID nvarchar(4) = 'FRA'
DECLARE @Dim7ID nvarchar(4) =  '' -- empty = all
DECLARE @Dim8ID nvarchar(4) = '' -- empty = all

DECLARE @Dim2 TABLE ( Dim2ID nvarchar(20) NOT NULL )
INSERT INTO @Dim2 VALUES ('A1'), ('A2'), ('A3'), ('A4');

DECLARE @Dim3 TABLE ( Dim3ID nvarchar(4) NOT NULL )
INSERT INTO @Dim3 VALUES ('P1');

DECLARE @Dim4ID TABLE ( Dim4ID smalldatetime NOT NULL )
INSERT INTO @Dim4ID VALUES ('2009-01-01'), ('2009-01-02'), ('2009-01-03');

DECLARE @Dim11 TABLE ( Dim11ID nvarchar(20) NOT NULL )
INSERT INTO @Dim11 VALUES ('Var0001'), ('Var0040'), ('Var0060'), ('Var0099')

SELECT   RD.Dim2ID,
         RD.Dim3ID,
         RD.Dim4ID,
         RD.Dim5ID,
         RD.Dim6ID,
         RD.Dim7ID,
         RD.Dim8ID,
         RD.Dim9ID,
         RD.Dim10ID,
         RD.Dim11ID,
         RD.Value
FROM     dbo.Test RD
         INNER JOIN @Dim2 R
           ON RD.Dim2ID = R.Dim2ID
         INNER JOIN @Dim3 C
           ON RD.Dim3ID = C.Dim3ID
         INNER JOIN @Dim4ID P
           ON RD.Dim4ID = P.Dim4ID
         INNER JOIN @Dim11 V
          ON RD.Dim11ID = V.Dim11ID
WHERE    RD.Dim1ID = @Dim1ID
         AND RD.Dim9ID = @Dim9ID
         AND ((@Dim6ID <> '' AND RD.Dim6ID = @Dim6ID) OR @Dim6ID = '')
         AND ((@Dim7ID <> '' AND RD.Dim7ID = @Dim7ID) OR @Dim7ID = '')
         AND ((@Dim8ID <>'' AND RD.Dim8ID = @Dim8ID) OR @Dim8ID = '')

Я проверил этот запрос, и этовернул 180 строк с таким временем: 1-е исполнение: 1 мин 32 с;2-е выполнение: 1 минута .

Я хотел бы вернуть данные через несколько секунд, если это возможно.

Я думаю, что могу добавить некластеризованные индексы, но я неуверен, что лучший способ - это установить некластеризованные индексы!Если сортировка данных заказа в этой таблице может улучшить производительность?Или есть другие решения, кроме индексов?

Спасибо.

Ответы [ 4 ]

3 голосов
/ 28 марта 2011

Рассмотрите ваши типы данных как одну проблему. Вам нужен nvarchar? Это заметно медленнее

Вторая проблема: ПК неверен для вашего запроса, сначала он должен быть Dim1ID, Dim9ID (или наоборот, в зависимости отселективность).или что-то вроде столбцов JOIN в.

Третья проблема: использование OR.Эта конструкция, как правило, работает, несмотря на то, что посты, которые не пытаются ее опубликовать.

RD.Dim7ID = ISNULL(@Dim7ID, RD.Dim7ID)

Это предполагает, что @ Dim7ID равен NULL.В большинстве случаев оптимизатор закоротит его.

2 голосов
/ 28 марта 2011

Я с ГБН на этом.Как правило, в хранилищах данных со звездообразной схемой идентификаторы измерений имеют тип int, то есть 4 байта.Мало того, что все ваши измерения больше этого размера, nvarchar может варьироваться и использовать широкие символы.

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

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

Но я беспокоюсь, что в вашем запросе указан параметр ID,Как правило, в среде DW вы не знаете идентификаторы, для выборочных запросов вы выбираете на основе измерений, а идентификаторы являются бессмысленными суррогатами:

SELECT *
FROM fact
INNER JOIN dim1
    ON fact.dim1id = dim1.id
WHERE dim1.attribute = ''

Вы смотрели книги Кимбалла по многомерному моделированию?Я думаю, что если вы собираетесь использовать схему типа «звезда», вы, вероятно, должны быть знакомы с его методами проектирования, а также с различными подводными камнями, которые он обсуждает со слишком многими и слишком малыми измерениями.

0 голосов
/ 28 марта 2011

Я бы немного беспокоился о наличии всех не значащих столбцов в вашем кластерном индексе. Это приведет к большому индексу на неконечных уровнях. И этот ключ будет использоваться в некластеризованных индексах. Кроме того, он будет обеспечивать какую-либо выгоду только тогда, когда [Dim1ID] включен в запрос. Таким образом, даже если вы оптимизируете только этот запрос, вы, вероятно, получаете полное сканирование.

Я бы рассмотрел кластеризованный индекс наиболее часто используемого ключа, и если у вас много запросов, связанных с датой (например, дата между a и b), используйте ключ даты. Затем создайте некластеризованные индексы для других ключевых значений.

0 голосов
/ 28 марта 2011

см. Это: Условия динамического поиска в версии T-SQL для SQL 2008 (SP1 CU5 и более поздних версий)

быстрый ответ, если вы используете правильный пакет обновления для SQL Server 2008, попробуйте добавить это в конец запроса:

OPTION(RECOMPILE) 

, когда на соответствующем пакете обновления SQL Server 2008, OPTION(RECOMPILE) будет строить план выполнения на основе значения времени выполнения локальногопеременные.

Для людей, которые все еще используют SQl Server 2008 без надлежащих пакетов обновления или все еще в 2005 году, см .: Условия динамического поиска в T-SQLVersion для SQL 2005 и более ранних версий

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...