Проблема фрагментации индекса SQL Server 2008 - PullRequest
3 голосов
/ 20 августа 2011

Каждый день я импортирую 2 000 000 строк из некоторых текстовых файлов, используя BULK INSERT, в SQL Server 2008, а затем выполняю некоторую постобработку для обновления записей.

У меня есть несколько индексов в таблице, чтобы выполнить постобработку как можно быстрее, и в обычной ситуации сценарию постобработки требуется около 40 секунд.

Но иногда (я не знаю, когда) постобработка не работает. В ситуации, которую я упомянул, это не сделано через час! После восстановления индексов все нормально и нормально.

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

Сейчас у меня есть ночная работа по перестройке всех индексов. Почему фрагментация индекса растет до 90%?

Обновление: Вот моя таблица, в которую я импортирую текстовый файл:

  CREATE TABLE [dbo].[My_Transactions](
    [My_TransactionId] [bigint] NOT NULL,
    [FileId] [int] NOT NULL,
    [RowNo] [int] NOT NULL,
    [TransactionTypeId] [smallint] NOT NULL,
    [TransactionDate] [datetime] NOT NULL,
    [TransactionNumber] [dbo].[TransactionNumber] NOT NULL,
    [CardNumber] [dbo].[CardNumber] NULL,
    [AccountNumber] [dbo].[CardNumber] NULL,
    [BankCardTypeId] [smallint] NOT NULL,
    [AcqBankId] [smallint] NOT NULL,
    [DeviceNumber] [dbo].[DeviceNumber] NOT NULL,
    [Amount] [dbo].[Amount] NOT NULL,
    [DeviceTypeId] [smallint] NOT NULL,
    [TransactionFee] [dbo].[Amount] NOT NULL,
    [AcqSwitchId] [tinyint] NOT NULL
) ON [PRIMARY]

GO

CREATE NONCLUSTERED INDEX [_dta_index_Jam_Transactions_8_1290487676__K1_K4_K12_K6_K11_5] ON [dbo].[Jam_Transactions] 
(
    [Jam_TransactionId] ASC,
    [TransactionTypeId] ASC,
    [Amount] ASC,
    [TransactionNumber] ASC,
    [DeviceNumber] ASC
)
INCLUDE ( [TransactionDate]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [_dta_index_Jam_Transactions_8_1290487676__K12_K6_K11_K1_5] ON [dbo].[Jam_Transactions] 
(
    [Amount] ASC,
    [TransactionNumber] ASC,
    [DeviceNumber] ASC,
    [Jam_TransactionId] ASC
)
INCLUDE ( [TransactionDate]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [IX_Jam_Transactions] ON [dbo].[Jam_Transactions] 
(
    [Jam_TransactionId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

Ответы [ 4 ]

2 голосов
/ 21 августа 2011

Вы пробовали просто обновить статистику после такой большой вставки:

UPDATE STATISTICS my_table

Мой опыт работы с большими объемными вставками заключается в том, что статистика полностью искажается и впоследствии требует обновления, это также намного быстрее, чем запуск REINDEX или индекса REORDER.

Другой вариант - изучить заполнение индекса. Вероятно, у вас нет коэффициента заполнения для индексов, что означает, что если индекс равен:

A, B, D, E, F

и вы вставите значение с CardNumber из C, тогда ваш индекс будет выглядеть так:

A, B, D, E, F, C

и, следовательно, быть ~ 20% фрагментированными, если вместо этого указать коэффициент заполнения для вашего индекса, скажем, 15%, мы увидим, что он выглядит примерно так:

A, B, D, _, E, F

(Обратите внимание, что внутреннее пустое пространство находится примерно в средней точке коэффициента заполнения%, а не в конце)

Так что, когда вы вставляете значение C, оно ближе к правильности, но на самом деле он видит, что D просто поменяется местами с C и обычно перемещает D в этой точке.

Кроме того, уверены ли вы, что на самом деле проблема заключается в фрагментации, так как часть переиндексации таблицы читается и загружается полностью в память (при условии, что она соответствует), и, таким образом, любой выполняемый вами запрос будет очень быстрым. *

1 голос
/ 20 августа 2011

Вместо того, чтобы включать эту таблицу в ночное задание, почему бы вам не сделать обслуживание индекса (особенно для этой таблицы) частью ночного задания импорта между BULK INSERT и какой бы то ни было «постобработкой»?

У нас недостаточно информации, чтобы знать , почему фрагментация индекса так быстро растет. Какой индекс (ы)? Сколько существует индексов? Каков порядок данных в файле?

Вы также можете использовать опцию ORDER в операторе BULK INSERT, чтобы изменить способ вставки данных. Это может заставить нагрузку занять больше времени, но это должно уменьшить необходимость реорганизации. Опять же, в зависимости от порядка исходных данных и индекса (ов), которые становятся фрагментированными.

Наконец, каково влияние перестройки / не перестройки или реорганизации / не реорганизации индексов? Вы пробовали оба? Возможно, это ускоряет последующую обработку, если вы перестраиваете, но, возможно, требуется только дефрагментация. И хотя это может ускорить постобработку, как насчет запросов, выполняемых к таблице позже в тот же день? Делали ли вы какие-либо метрики против тех, чтобы увидеть, ускоряются они или замедляются в зависимости от того, что вы делаете ночью?

0 голосов
/ 29 августа 2012

Я бы попытался перевести индекс в автономный режим перед массовой вставкой строки и вернуть его в оперативный режим после массовой вставки строки. Намного, гораздо быстрее по сравнению с повторной индексацией или выполнением удаления и создания индекса ... разница в том, что индекс там, где хранятся данные, но индекс в настоящее время не используется, "автономно", пока не будет вернул "Онлайн". У меня 1,5 миллиона операций вставки строк, и у меня возникла проблема с фрагментированием одного из моих некластеризованных индексов, что привело к снижению производительности. Фрагментация от 99% до 0,14% с использованием параметра автономного онлайн-индекса MSSQL ....

Пример кода:

ALTER INDEX idx_a ON dbo.tbl_A
REBUILD WITH (ONLINE = OFF);

Переключение между ВЫКЛ и ВКЛ, и вы готовы идти ....

0 голосов
/ 20 августа 2011

Ваша основная таблица продолжает расти на 2 миллиона строк в день или также происходит много удалений? Не могли бы вы выполнить массовую вставку во временную таблицу импорта и выполнить обработку перед вставкой в ​​основную таблицу? Вы всегда можете использовать подсказки, чтобы заставить ваши запросы использовать определенные индексы:

SELECT *
FROM your_table_name WITH (INDEX(your_index_name))
WHERE your_column_name = 5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...