Какие индексы я должен создать на этой таблице в SQL Server? - PullRequest
0 голосов
/ 05 июля 2018

У меня есть таблица со следующим определением:

CREATE TABLE [dbo].[Transactions]
(
    [ID] [varchar](18) NOT NULL,
    [TIME_STAMP] [datetime] NOT NULL,
    [AMT] [decimal](18, 4) NOT NULL,
    [CID] [varchar](90) NOT NULL,
    [DEPARTMENT] [varchar](4) NULL,
    [SOURCE] [varchar](14) NULL,
    PRIMARY KEY NONCLUSTERED 
    (
        [ID] ASC
    )
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Таблица содержит 75 миллионов строк. Почему-то это занимает 20 ГБ дискового пространства!

Следующие 2 запроса ...

SELECT 
    SUM(AMT) 
FROM 
    Transactions
WHERE 
    TIME_STAMP >= '2017-11-11 00:00:00' AND 
    TIME_STAMP < '2017-11-12 00:00:00'


SELECT 
    COUNT(DISTINCT(CID))
FROM 
    Transactions
WHERE 
    TIME_STAMP >= '2017-11-11 00:00:00' AND 
    TIME_STAMP < '2017-11-12 00:00:00'

... каждый занимает около 2 минут, чтобы бежать!

Кстати, у таблицы есть «Clustered ColumnStore Index», которую я не могу удалить, так как в прошлый раз, когда я пытался удалить ее, произошел сбой DROP из-за недостатка места на диске. На жестком диске, на котором хранятся данные, после сжатия БД 28 ГБ освобождаются от 50 ГБ.

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

Кроме того, что, если мне также необходимо указать DEPARTMENT и SOURCE в некоторых предложениях WHERE? Эти столбцы имеют только несколько различных значений.

Спасибо!

Ответы [ 4 ]

0 голосов
/ 05 июля 2018

Я думаю, что одного индекса будет достаточно:

create index idx_transactions_timestamp_cid_amt on transactions(timestamp, cid, amt);

Это относится к первому запросу. cid в индексе не имеет отношения к использованию индекса для запроса. Индекс будет отсканирован на основе даты. Вы можете выбрать «включить» amt вместо включения его в качестве отдельного ключа.

0 голосов
/ 05 июля 2018

Общее правило заключается в том, чтобы индексировать столбцы в предложении where и любых предикатах объединения, НО это грубое руководство, и не просто дико применяйте подсказки индекса из SSMS, они часто лгут, если они будут лучше

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

, например

CREATE INDEX IX_TEST1 on Transactions (TIME_STAMP) INCLUDE (AMT)
CREATE INDEX IX_TEST1 on Transactions (TIME_STAMP) INCLUDE (CID)

Недостатком является то, что это поля date и varchar, поэтому индексы станут довольно большими

0 голосов
/ 05 июля 2018

Вам нужен кластеризованный индекс в вашей таблице (который обычно является первичным ключом, который может состоять из одного или нескольких столбцов, которые объединяются в уникальное значение. Кластерный индекс не обязательно должен быть уникальным, но первичный ключ делает. I Я бы предположил, что идентификатор является хорошим кандидатом для первичного ключа. Затем я создал бы один индекс на основе time_stamp и включил бы CID и Amt.

Вы хотите, чтобы ваш запрос использовал поиск (что означает, что SQL Server читает только соответствующие строки) вместо сканирования (при котором SQL Server читает всю таблицу).

Опять же, мы не видим данных, но я бы предложил следующее:

alter table [dbo].[Transactions] add constraint PK_transactions_id primary key ( id);
create index ix_transactions_time_stamp_amt on transactions(timestamp) include (cid,amt);
0 голосов
/ 05 июля 2018

Создание индекса на Time_Stamp, который ВКЛЮЧАЕТ AMT и CID, должен оптимизировать запросы в вашем вопросе.

«Почему» - это широкая тема, которая не очень подходит для ответа о переполнении стека. Читайте учебные пособия и блоги по индексированию SQL Server.

РЕДАКТИРОВАТЬ ответ на комментарий:

Столбцы, которые вы фильтруете в предложении WHERE, должны быть частью самого индекса (даже если они имеют только несколько отдельных значений), столбцы, которые вы просто возвращаете в списке SELECT, должны быть частью предложения INCLUDES индекса .

...