Низкая производительность вставки при вставке записей в таблицу с не кластеризованным PK с GUID - PullRequest
1 голос
/ 23 марта 2019

Я сравниваю производительность вставки SQL Server 2017 для таблицы с некластеризованным первичным ключом (GUID) и дополнительным кластеризованным индексом (int). Несмотря на то, что я ожидал некоторого снижения производительности по сравнению с PK для автоинкрементных целочисленных значений, полученные показатели не кажутся разумными - вставка в таблицу с GUID PK занимает буквально в 70 раз больше времени.

Таблица:

[Table1]
(
    [Id] [INT] IDENTITY(1,1) NOT NULL, <-- clustered PK
    [Prop_s1] [NVARCHAR](MAX) NULL,
    [Prop_s2] [NVARCHAR](MAX) NULL,
    ...
    [Prop_b3] [BIT] NULL,
    [Prop_n3] [DECIMAL](18, 2) NULL
)

[Table2]
(
    [Id] [UNIQUEIDENTIFIER] NOT NULL, <-- non-clustered PK
    [Prop_s1] [NVARCHAR](MAX) NULL,
    [Prop_s2] [NVARCHAR](MAX) NULL,
    ...
    [Prop_b3] [BIT] NULL,
    [Prop_n3] [DECIMAL](18, 2) NULL,
    [ClusterId] [INT] IDENTITY(1,1) NOT NULL, <-- clustered
)

Запросы выглядят как

Insert into Table (....)
    select ....
    union all
    select ....

Идентификаторы для Table2 генерируются на стороне клиента.

Обе таблицы идентичны по структуре.

Я могу вставить 10 тыс. Записей за 550-600 мс с автоинкрементом int PK. С помощью направляющих клавиш это занимает около 35 секунд на 10 тыс. Строк.

Ответы [ 2 ]

3 голосов
/ 23 марта 2019

Вставка случайных GUID в некластеризованную PK имеет те же проблемы, что и вставка случайных GUID в кластеризованную PK, но в меньшей степени.Каждая строка помещается на «случайную» страницу, и страницы заполняются и должны быть разделены.

И с некластеризованным ПК у вас есть ненужный индекс для поддержки.

Этолучше иметь кластерный индекс в Guid и NEWSEQUENTIALID () или последовательную генерацию GUID на стороне клиента.

Последовательная генерация GUID на стороне клиента требует переупорядочения некоторых байтов для согласования с тем, как SQL Server сортирует GUID.В C # на Windows это выглядит так:

  public class SQLGuidUtil
  {
      [DllImport("rpcrt4.dll", SetLastError = true)]
      static extern int UuidCreateSequential(out Guid guid);

      public static Guid NewSequentialId()
      {
        Guid guid;
        UuidCreateSequential(out guid);
        var s = guid.ToByteArray();
        var t = new byte[16];
        t[3] = s[0];
        t[2] = s[1];
        t[1] = s[2];
        t[0] = s[3];
        t[5] = s[4];
        t[4] = s[5];
        t[7] = s[6];
        t[6] = s[7];
        t[8] = s[8];
        t[9] = s[9];
        t[10] = s[10];
        t[11] = s[11];
        t[12] = s[12];
        t[13] = s[13];
        t[14] = s[14];
        t[15] = s[15];
        return new Guid(t);
      }
  }
0 голосов
/ 23 марта 2019

попробуйте использовать NEWSEQUENTIALID () вместо newid () для генерации уникального идентификатора.Как правило, я бы поставил столбец IDENTITY, если в этой таблице происходит много вставок

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