Може статися, що невелика кількість даних досягне певної межі в SQL Server, щоб змусити інший план або щось подібне. Це малоймовірно. Але той факт, що ваш диск, здається, сильно перебуває під обов'язком, підводить мене до іншого висновку.
Існує 2 можливих базових причини вашого сповільнення.
- Ви оновили систему та перезавантажили її
- Ви завантажуєте в неї купу даних
Давайте розглянемо частину №1
Можливо, ваша конфігурація SQL Server може бути порушена. Це може спричинити серйозні проблеми щодо швидкості вашого сервера та використання диска.
Перевірте в першу чергу основні настройки сервера. Ці основні параметри max server memory
, affinity I/O mask
, affinity mask
і max degree of parallelism
. Можливо, вам потрібно буде включити розширені параметри, використовуючи show advanced options
.
Ось повний сценарій:
-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'
Порівняйте результат із задокументованими значеннями на етапі встановлення. Вони все-таки однакові?
Це може бути багато причин, чому ваш сервер поводиться так дивно. Я б, як правило, робив ставку, що ви max server memory
просто помиляєтесь. Це призведе до того, що ваш SQL Server буде постійно міняти сторінки даних. Він не може утримати все в своїй пам'яті. Це означає, що йому потрібно прочитати сторінки з диска, оновити його, миттєво записати його назад. Якщо з'являється інше оновлення, яке використовує ту саму сторінку для оновлення, воно не може бути прочитане з пам'яті. Натомість серверу потрібно знову прочитати його з диска. Просто поміняти ...
Іншою проблемою може бути висока спорідненість на диску чи процесах. Якщо ви використовували спільний сервер (SQL Server + інші служби) з виділеним диском для SQL Server (що може бути рідкісним випадком, але це може бути), це може бути вашою проблемою. Ваш сервер зазвичай мав, наприклад, 3 процесора для процесів і один для вводу / виводу. Інші 12 процесорів використовуються для інших послуг. У цьому випадку ваша маска спорідненості неправильна і використовує, наприклад, автоматичну конфігурацію. Це означає, що Ваш сервер динамічно використовує всі 16 ядер для процесів і вводу / виводу. Якщо у вас запущені величезні процеси, вони можуть поставити величезне навантаження на диск, який він може не впоратися. Але насправді я не вірю, що це ваш випадок. Це було б швидше (навіть якби трохи), якби це застосовувалося, але ваш випадок - це сповільнення.
Іншою проблемою може бути занадто високий ступінь паралелізму. Це означає, що у вас є занадто багато темпів на холостому ходу в одній частці запиту. Це також може спричинити величезне уповільнення, якщо паралелізм не буде працювати так, як очікувалося. Але це не описує ваш високий вхід / вивід усього.
Тепер давайте подивимось і на частину №2
Ви завантажуєте купу рядків у вашу систему. Навіть якщо це звичайна робота, це може підвищити межу, в якій ваші плани запитів ескалюватимуть. Можливо, навіть так, що ваша вставка в поєднанні з SQL Server викликає таку поведінку.
Ви згадали, що ви вже намагалися перенести свої індекси на інший диск, який, здається, допомагає. Це може статися лише тому, що ви розділили навантаження на два різні диски.
Можливо, ваші індекси були розбиті, ваші плани були розбиті або статистика застаріла.
1. дозволяє перевірити статистику останнього оновлення.
Це можна зробити вручну через інтерфейс для кожного окремого елемента статистики. Що було б болем. Або ви можете спробувати цей код:
SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Це дасть вам повну інформацію про кожен індекс (і купу) та статистику за ними. Навіть якщо ви запустили, sp_updatestats
це не означає, що статистика була оновлена. Частина, коли оновлення досить складне, навіть якщо ви запускаєте sp_updatestats
або навіть якщо auto update statistics
воно ввімкнено, статистика не буде оновлюватися вчасно. Ось кілька кращих моментів, коли потрібно / генерується оновлення:
- Порожня таблиця отримує один або кілька рядків
- Таблиця, що містить понад 500 рядків, оновлює 20% + 500 додаткових рядків, а вставка відбулася згодом
- Коли було змінено 500 рядків у таблиці, що містить менше 500 рядків
Це означає, що ваша статистика може бути застарілою, навіть якщо ви запустите оновлення.
Ви можете подивитися на запит вище. Якщо ви знайдете досить стару статистику в деяких таблицях, ви можете запустити вручну оновлення статистики для цієї таблиці:
UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN
Після цього, можливо, ви захочете дати своєму серверу поштовх в дупу, щоб викинути всі старі плани.
DBCC FREEPROCCACHE
Якщо ви просто хочете очистити всі кеші, ви можете запустити це:
DBCC FREESYSTEMCACHE ('ALL')
Це очистить усі кеші, а не лише кеш плану. Зазвичай я попереджую, використовувати це на виробничому сервері у фазі виробництва. Але оскільки ваш сервер зараз не працює, ви не можете їм завдати великої шкоди. Це може сповільнитися на кілька секунд, може, 1-2 хвилини, оскільки йому потрібно відновити всі кеші, але після цього він повинен працювати з правильними планами.
Ще однією причиною можуть бути повністю фрагментарні індекси. Це можна перевірити на всьому сервері за допомогою цього оператора:
SELECT *
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)
Якщо фрагментація дуже велика, можливо, вам доведеться реорганізувати (фрагментація <20%) або повністю відновити (> 20%) її. Це може зайняти більший тиск на ваш диск і призвести до неприємностей. З іншого боку, якщо показники будуть такими поганими, це, мабуть, допоможе врешті більше, ніж шкодить.
Крім цих двох причин, існує ще третя проблема
Можливо, ваш сервер налаштований, ймовірно, ви не змінили жодного коду за цей час, просто додали кілька рядків. Вся статистика оновлюється, а всі кеші відновлюються. Усі ваші індекси реорганізовані так, як вам потрібно, але все одно - нічого не працює. Можливо, ви досягли межі доступної пам'яті у своїх процесах. Можливо, вам потрібно більше. Ви можете просто перевірити, чи є якийсь процес, який намагається отримати більше пам'яті, ніж у вас.
Ви можете перевірити це за допомогою цієї команди:
SELECT * FROM sys.dm_exec_query_memory_grants
Він надасть вам список усіх сеансів, які вимагають пам'яті. Можливо, буде якийсь запит, який ще чекає, щоб отримати пам'ять. Ці запити можна легко відфільтрувати. Усі сесії де granted_memory_kb IS NULL
. Це сеанси, які вимагають пам'яті, але не отримують її. Інша річ може бути наданою пам'яттю, яка може бути низькою. Ви можете порівняти стовпці requested_memory_kb
з granted_memory_kb
. Запрошений показує, скільки пам’яті потрібно для оптимального запуску процесу при наданні, відображається пам’ять, яка ввімкнена для процесу. Якщо для запуску процесу потрібно 2 Гб, але отримує лише 2 Мб ..., ви можете отримати його самостійно. ;-)
Ще один спосіб - перевірити RESSOURCE_SEMAPHORE
:
SELECT * FROM sys.dm_exec_query_resource_semaphore
Ви можете подивитися на waiter_count
та grantee_count
. Якщо офіціант вище 0, ти тиснеш на пам’ять, що може спричинити заміну і може спричинити тиск на диску, який ти бачив у парфмоні.