Очень низкая производительность вставки в большую таблицу (EF)

В одной из наших систем есть таблица, которая получает около 20 тысяч вставок в день — в настоящее время она содержит около 10 миллионов строк. Мы только что выпустили обновление системы, и теперь я получаю ужасно низкую производительность при вставках в эту таблицу (30-40-секундные трассировки). Вставки будут вставлять только одну строку за раз. Entity Framework генерирует следующий SQL:

declare @generated_keys table([ID] uniqueidentifier)

insert [dbo].[Table]([Col1], Col2], etc)

output inserted.[ID] into @generated_keys values (@0, @1, etc)

select t.[ID] from @generated_keys as g join [dbo].[Table] as t on g.[ID] = t.[ID] where @@ROWCOUNT > 0

Ничего необычного - по крайней мере, насколько я вижу.

В таблице 12 FK. Поскольку объект представляет событие, основанное на времени, кластеризованный индекс находится в столбце DateCreated. Есть еще 8 некластеризованных индексов с различными включенными столбцами. Столбец ID является ПК и имеет уникальный некластеризованный индекс.

В качестве примечания я заметил, что из-за упущения в столбце ID используется newid() вместо newsequentialid().

Фактический план выполнения состоит из следующих основных частей:

7x 3% — поиск кластеризованного индекса в FK-таблицах

1x 8% — вставка таблицы (@generated_keys)

1x 74% — вставка кластеризованного индекса, 1 фактическая строка, стоимость 0,09

Я действительно хотел бы добраться до сути этого, но я сейчас в тупике. Любой совет?


person James    schedule 24.05.2016    source источник
comment
Вы пытались отказаться от ClusteredIndex?   -  person Mike Miller    schedule 24.05.2016
comment
Это на месте, так как почти все операции выбора в этой таблице возвращают данные в порядке дат. Кроме того, учитывая, что вставки упорядочены по дате, кластерный индекс в этом столбце, на мой взгляд, имеет смысл, а не использование столбца PK (uniqueidentifier).   -  person James    schedule 24.05.2016
comment
Медленно работающая вставка постоянна или у вас так много работает быстро, а не одна занимает возраст?   -  person Martin Brown    schedule 24.05.2016
comment
Как ты сказал. Первый запрос в серии/пакете может занять некоторое время, но последующие запуски выполняются очень быстро (со скоростью, которую я всегда ожидаю).   -  person James    schedule 24.05.2016
comment
кажется, проблема не в самом запросе, а в управлении соединением/построении модели. Какой из них я не могу точно сказать, однако я предполагаю последнее, поскольку модель кажется сложной.   -  person DevilSuichiro    schedule 24.05.2016


Ответы (1)


Как вы уже заметили, SaveChange совершает круговой обход базы данных для каждой вставки записи. Таким образом, если вы добавляете 20 000 записей в день, выполняется 20 000 обращений к базе данных.

Модификация и улучшение индекса почти ничего не изменит, поскольку реальная проблема заключается в количестве обращений к базе данных!

Чтобы исправить производительность, вы должны использовать библиотеку, которая позволяет выполнять массовую вставку

Его поддерживают три основные библиотеки:

Вы можете узнать больше об этих трех библиотеках здесь: Обзоры и сравнения библиотек массовой вставки Entity Framework

Отказ от ответственности: я являюсь владельцем проекта Entity Framework Extensions

person Jonathan Magnan    schedule 24.05.2016
comment
Массовые вставки не являются проблемой, эти 20k вставки происходят в течение 24 часов. Сохранение их для массовой вставки не вариант. - person James; 24.05.2016