Индексирование, чтобы проверить, содержит ли очень большая таблица точную строку в определенном столбце - PullRequest
0 голосов
/ 25 сентября 2018

У меня очень большая таблица SQL (~ 500 миллионов строк)

CREATE TABLE [dbo].[TestDefinition]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](500) NOT NULL,
    [TeamId] [int] NOT NULL,

    CONSTRAINT [PK_Test] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
GO

Я хочу вставить новые записи в таблицу, но сначала мне нужно убедиться, что запись еще не существует.

Я по сути строю таблицу со значениями (@TestDefinitionInput - TVP), которую я хочу вставить, а затем передаю ее в хранимую процедуру.

WITH W AS 
(
   SELECT [Name], TeamId
   FROM @TestDefinitionInput
),
X AS 
(
   SELECT W.* 
   FROM W
   LEFT JOIN TestDefinition td ON td.TeamId = W.TeamId AND td.[Name] = W.[Name] 
   WHERE td.Id IS NULL
)
INSERT INTO TestDefinition ([Name], [TeamId]) 
   SELECT [Name], [TeamId]
   FROM X;

Моя проблема в том, что этодействительно slooow с 500 миллионами строк.Я действительно не очень хорошо разбираюсь в SQL и мне интересно, как мне следует, если нужно, индексировать dbo.[TestDefinition], чтобы сделать это как можно быстрее.

1 Ответ

0 голосов
/ 25 сентября 2018

У вас есть несколько возможностей:

Вы можете рассмотреть возможность изменения вашего первичного ключа на:

CONSTRAINT [PK_Test] 
    PRIMARY KEY CLUSTERED (TeamId ASC, [Id] ASC)

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

Другой ( вероятно предпочтительный ) вариант заключается в создании некластеризованного индекса:

CREATE INDEX IX_TestDefinition_TeamId_Name 
    ON dbo.TestDefinition(TeamId, Name)

[Примечание: нет необходимости явно ВКЛЮЧИТЬ Id, поскольку это ключ кластеризации, который добавляется к каждому некластеризованному индексу.]

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

Я также рассмотрел бы добавление индекса со сжатием страниц (и таблицы, если вы можете)

.... with (data_compression = page);

Сжатие данных не доступно в каждой редакции SQL Server.SQL Server 2016 и более поздних версий выпущен в стандартной версии.

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

...