Как улучшить производительность запросов 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

Ключ кластеризации - это то, как каждый индекс указывает на остальную часть таблицы.

Поможет ли создание 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/

Другие вопросы по тегам