Требуется объяснение медленного УДАЛЕНИЯ с SQL Server

8

Я хотел бы получить некоторые дополнительные сведения / обоснование поведения удаления SQL Server. У нас довольно большая база данных более 1800 ГБ.

Есть несколько очень мелких таблиц (всего несколько целочисленных столбцов) с миллионами строк. Когда мы удаляем 10000 строк из этих мелких таблиц, запросы на удаление, как правило, выполняются довольно быстро (не более нескольких секунд).

У нас также есть таблица с полем imageхранения типов изображений в среднем 100 КБ. Когда мы удаляем только несколько тысяч строк из этой таблицы, это занимает больше минуты.

Хотя разница очевидна (гораздо больше данных удаляется по размеру), мне не терпится узнать больше о том, что происходит внутри SQL Server. Так что я могу лучше понять, что последние удаляются намного медленнее.

Кто-нибудь может пролить свет?

marc_s
источник
Есть книга по внутренним компонентам SQL Server, если вы заинтересованы в подобных вещах и хотите услышать от близких к источнику.
Stakx
Я подозреваю, что при удалении изображения происходит много случайных операций ввода-вывода, или они что-то блокируют. Удаление нескольких 1000 строк никоим образом не приведет к минуте полной загрузки ЦП.
USR

Ответы:

10

гораздо больше данных по размеру удаляется

Удаление блоба размером 100 imageКБ на самом деле не является операцией с размером данных. BLOB-объект освобождается, а не удаляется, и запись полного изображения отсутствует. Вы можете легко проверить это:

create database blob
go

use blob
go

create table t (id int not null identity(1,1), blob image)
go

insert into t (blob) values (
  replicate(
    cast(0x000102030405060708090a0b0c0d0e0f as varbinary(max)), 
    100*1024/16))
go 10

alter database blob set recovery full
go

backup database blob to disk='nul:'
go

delete from t where id = 3
go

select * from fn_dblog(null, null)
go

Записи журнала, которые вы увидите, будут выглядеть примерно так:

00000026:0000008e:0001  LOP_BEGIN_XACT  LCX_NULL    0000:00000304   0x0000  76  124
00000026:0000008e:0002  LOP_LOCK_XACT   LCX_NULL    0000:00000304   0x0000  24  56
00000026:0000008e:0003  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0004  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0005  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0006  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0007  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0008  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0009  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:000a  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:000b  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:000c  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
...    
00000026:0000008e:0022  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0023  LOP_DELETE_ROWS LCX_TEXT_MIX    0000:00000304   0x0000  62  172
00000026:0000008e:0024  LOP_DELETE_ROWS LCX_HEAP    0000:00000304   0x0000  62  120
00000026:0000008e:0025  LOP_COMMIT_XACT LCX_NULL    0000:00000304   0x0000  80  84

Как видите, для строки, содержащей imageстолбец, нет записи «DELETE» с данными +102400 байт . Есть множество освобождений (операция PFS / IAM / GAM) и простое удаление строк (в моем случае куча выглядела бы очень похоже на B-Tree, если бы я помнил, чтобы объявить ID как PK ...). Дополнительные сведения см. В разделе « Как читать и интерпретировать журнал SQL Server» .

Что оставляет открытым исходный вопрос: почему одно удаление медленнее другого? Я рекомендую вам прочитать Как анализировать производительность SQL Server . Следуйте методике, описанной, чтобы зафиксировать ожидания конкретного утверждения и посмотреть, в чем причина. См. Анализ выполнения отдельного запроса , особенно часть об Анализе времени ожидания выполнения отдельного запроса. Только после того, как вы измерили, мы сможем ответить на загадку. Причин может быть много: больше блокировок из-за одновременного чтения таблицы BLOB-объектов, отсутствующих индексов для поиска строк-кандидатов DELETE в одной таблице, запуска триггеров и т. д. и т. д. Связанная методология поможет вам точно определить причину.

Ремус Русану
источник