Как улучшить производительность запросов SQL Server
Размер таблицы 32ГБ Количество строк 250М
Стол DDL
CREATE TABLE Orders
(
ID [int] IDENTITY(1,1) NOT NULL,
server [varchar](50) NULL,
server_id [int] NOT NULL,
merchant_id [int] NOT NULL,
order_id [int] NOT NULL,
customer_id [int] NOT NULL,
customer_name [varchar](50) NULL,
[amount] [money] NULL,
order_date [smalldatetime] NULL,
ship_date [smalldatetime] NULL,
order_status [varchar](50) NULL,
custom_field_1 [varchar](50) NULL,
custom_field_2 [varchar](50) NULL,
custom_field_3 [varchar](50) NULL,
custom_field_4 [varchar](50) NULL,
created_at [datetime] NULL
CONSTRAINT [PK_Orders]
PRIMARY KEY CLUSTERED ([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]
У меня есть следующий некластеризованный индекс
merchant_id, order_id
order_date
Логично, что order_id
, merchant_id
сделать уникальный ключ.
Простой запрос, как показано ниже, занимает почти 30 минут.
select
sum(amount)
from
Orders
where
Order_Date >= getdate() - 7
У меня есть несколько вопросов:
- ПК прав? В настоящее время он находится в поле ID и не используется ни для чего.
- Будет делать
order_id
а такжеmerchant_id
как ПК помогают в исполнении? - Каковы идеальные индексы, которые я должен иметь в этой таблице?
3 ответа
Прав ли ПК?
Наверное. Используя этот суррогат id
для ключа кластеризации снижает затраты на хранение для всех индексов, используя тонкий 4-байтовый ключ вместо составного 12-байтового ключа merchant_id, order_id, order_date
или 8-байтовый ключ merchant_id, order_id
Ключ кластеризации - это то, как каждый индекс указывает на остальную часть таблицы.
- Дискуссия по кластерному индексу продолжается... - Кимберли Трипп
- Дополнительные соображения по поводу ключа кластеризации - дебаты по кластерному индексу продолжаются! - Кимберли Трипп
- Сколько стоит этот ключ? (плюс sp_helpindex9) - Кимберли Трипп
Поможет ли создание order_id и merchant_id как PK помочь в производительности?
Вам нужно будет проанализировать влияние всех запросов, выполняемых к таблице, чтобы узнать, поможет ли это или нет.
Я бы сфокусировался на оценке покрывающих индексов для запросов, которые вам нужны для более быстрой работы, и если вы обнаружите тенденцию, где вам нужны эти два столбца для большинства ваших запросов, то, возможно,.
Каковы идеальные индексы, которые я должен иметь в этой таблице?
Вам необходимо просмотреть запросы, планы выполнения и текущее использование индексов, чтобы определить, какие индексы вам нужны для этой таблицы.
Так как ваш order_date
это не первый столбец в вашем некластеризованном индексе, оптимизатор, скорее всего, не будет использовать его для вашего примера запроса.
Даже если у вас есть индекс на order_date
придется вернуться к столу, чтобы получить amount
, Если вы включите amount
в качестве включенного столбца в индексе он станет промежуточным индексом для этого запроса, и нет необходимости возвращаться к таблице.
Для этого примера запроса вы могли бы использовать что-то вроде этого, чтобы иметь запрос только для индекса, вместо запроса с поиском в таблице:
create nonclustered index ix_Orders (Order_Date) include (amount);
Вам просто нужно изменить индекс Order_Date, чтобы он охватывал индекс, включая столбец Amount. То же самое предлагает @Lamark https://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/
Что вам нужно, это индекс на дату. Создайте некластеризованный индекс на дату, это поможет в производительности. Индексирование очень важно для производительности запросов. Просто для начала у вас должен быть индекс для тех столбцов, которые интенсивно используются в предложении where в поле даты вашего дела.
https://www.simple-talk.com/sql/learn-sql-server/sql-server-index-basics/