Назад | Перейти на главную страницу

Медленный MSSQL на БД (~ 2 ТБ) - Индекс / фрагментация?

У меня довольно большая база данных MS SQL (~ 2 ТБ). Большая часть данных находится в одной таблице (~ 6 миллиардов строк).

Две недели назад я сбросил два некластеризованных индекса в большую таблицу и перенес данные на один RAID-массив SSD объемом 6 ТБ. Затем я воссоздал два индекса, что заняло довольно много времени (при условии, что в настоящее время у меня есть данные (для таблицы и индексов), и я регистрируюсь в том же массиве, и кажется, что с RAID у меня не может быть быстрого последовательного И случайного r / w в то же время).

В любом случае, после воссоздания индексов он работал очень хорошо около недели. В течение недели я медленно выполнял чистку на большом столе, который просто удалял старые ненужные строки. На данный момент я удалил около 300 миллионов из 6 миллиардов, и предполагаю, что мне еще многое предстоит сделать.

Примерно через неделю подобного бега он теперь работает очень медленно, и я не уверен, что было бы лучше сделать.

Текущая ситуация:

В большой таблице в настоящее время есть (до сих пор у меня нет информации о фрагментации):

Как вы думаете, что лучше всего решит мою проблему

Вызывают ли фрагментированные индексы более высокую загрузку ЦП?

Что еще мне могло не хватать?

TIA

В зависимости от степени фрагментации ваших индексов вы должны пойти дальше и перестроить их. Любой индекс с фрагментацией более 30% следует перестроить. Я также хотел бы убедиться, что вы регулярно обновляете статистику в таблице (перестройка индекса сделает это за вас автоматически).

После этого, если вы по-прежнему увидев действительно высокую загрузку ЦП и подтвердив, что это процесс SQLServr.exe, вам нужно сузить круг запросов, которые используют так много ЦП, и устранить их оттуда.

Вы можете запустить что-то вроде следующего запроса, чтобы получить некоторые агрегированные данные о запросах, которые использовали большую часть ЦП:

SELECT TOP 5 total_worker_time/execution_count AS [Avg CPU Time],
total_logical_writes as [Total Writes],
total_logical_reads as [Total Reads],
SUBSTRING(st.text, (qs.statement_start_offset/2)+1, 
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
ORDER BY total_worker_time/execution_count DESC;

Для данных в реальном времени вы также можете запустить что-то вроде этого:

SELECT er.session_id, er.cpu_time, er.reads, er.writes, 
SUBSTRING(st.text, (er.statement_start_offset/2)+1, 
((CASE er.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE er.statement_end_offset
END - er.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_requests AS er
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) as st
WHERE session_id > 50
AND status = 'runnable'
ORDER BY cpu_time desc

Вы также можете запустить оба, чтобы сравнить данные в реальном времени с агрегированными данными. Оба должны дать вам представление о том, что использует столько ЦП. Оттуда вы захотите узнать, почему они так долго бегают. Они делают тонну чтения или тонну записи? Если они выполняют много операций чтения, это может означать, что им не хватает некоторых индексов. Тонны операций записи могут означать, что на самом деле проблема заключается в индексах.

В любом случае наблюдение за этими утверждениями может дать вам отправную точку.