Ускорить UPDATE

prozaeck
Дата: 23.01.2009 00:00:41
MS sql server 2000 (MSDE). Нужно ускорить update таблицы
CREATE TABLE dbo.T_PRO_PLAST
(
ID_PROPLAST                         INT IDENTITY(1,1) NOT NULL,
POR_PP                              REAL,
GLIN_PP                             REAL,

 еще 30 столбцов - все REAL,
 есть и другого типа, но они не обновляются 


CONSTRAINT PK__T_PRO_PLAST__7E6372D6 PRIMARY KEY CLUSTERED ( ID_PROPLAST )
)

UPDATE делаю так
update T_PRO_PLAST set POR_PP = 33.33, GLIN_PP = 44.44
where ID_PROPLAST = 1100

В таблице 26 тысяч строк ( будет 50-200 тысяч ).
Update делаю 3 тысячам ( будет 30-50 тысяч)
Время 0.6 - 0.8 секунды. На Core2duo 3.6Гц 4гб оперативки.
Select этих же строк быстрее ~ 50 раз.

Вопросы:
1. Это и так очень быстро и ускорить в разы не реально?

2. В чем конкретно тормоз

2. Если в запрос добавить
    from T_PRO_PLAST with(index(0)) 
время выполнения -12 секунд. Означает ли это, что индексирование работает на 100% и здесь ничего не выжать?

3. Если в запрос добавить
    from T_PRO_PLAST with(index(PK__T_PRO_PLAST__7E6372D6)) 
время выполнения - 2.8 секунды. Почему? Разве таким образом не указывается тот же самый индекс, что используется по умолчанию?

5. Есть ли способ у этого индекса поиграться с fill factor не создавая таблицу заново?

6. Замена UPDATE на DELETE и INSERT может помочь?
Senya_L
Дата: 23.01.2009 00:09:41
prozaeck,

покажите план запроса
Mr Marmelad
Дата: 23.01.2009 00:13:25
prozaeck,

А у Вас там никаких побочных триггеров нет, Коллега? Или там RI констраинты?
prozaeck
Дата: 23.01.2009 01:34:32
Senya_L,
К моему стыду, а не знаю что это такое. Запросы тестирую в SQLExecMS. Могу выложить хранимую процедуру. Но в ней кроме UPDATE ничего интересного нет. Клиенское приложение на СSharp. Запрос выполняется так:
SqlCommand cmd = new SqlCommand();
cmd.Connection = 
cmd.CommandText = "UPDATE ...."
cmd.ExecuteNonQuery();
Это без хранимой процедуры. Но с ней примерно тоже самое.
Еще пробовал в cmd.CommandText передавать по 1000 UPDATE'ов через ';' - ускорения нет.
prozaeck
Дата: 23.01.2009 01:41:31
Mr Marmelad,

Полный текст таблицы:
CREATE TABLE dbo.T_PRO_PLAST
(
ID_PROPLAST                         INT IDENTITY(1,1) NOT NULL,
ID_WELL                             INT,
TOP_PLAST                           REAL,
BOT_PLAST                           REAL,
ATOP_PLAST                          REAL,
ABOT_PLAST                          REAL,
DATE                                DATETIME,
HEFF                                REAL,
POR_PP                              REAL,
GLIN_PP                             REAL,
PRON_PP                             REAL,
OIL_GAS_SAT_PP                      REAL,
SAT_TYPE                            NVARCHAR(255) DEFAULT ('ÎÒÑÓÒ') NOT NULL,
PP_GR                               REAL,
UM1                                 REAL,
UM2                                 REAL,
ID_VIEW_ROW                         INT,
upsize_ts                           TIMESTAMP,
PP_CLmf                             REAL,
PP_CLR                              REAL,
PP_CLvf                             REAL,
PP_dJg                              REAL,
PP_dJng                             REAL,
PP_DTC                              REAL,
PP_DTCC                             REAL,
PP_EPOR                             REAL,
PP_HI                               REAL,
PP_HING                             REAL,
PP_K                                REAL,
PP_LL                               REAL,
PP_NGPOR                            REAL,
PP_NGR                              REAL,
PP_RI                               REAL,
PP_RL                               REAL,
PP_RR                               REAL,
PP_RW                               REAL,
PP_SH                               REAL,
PP_SPOR                             REAL,
PP_SPORC                            REAL,
PP_SR                               REAL,
PP_SW                               REAL,
PP_SWR                              REAL,
CONSTRAINT PK__T_PRO_PLAST__7E6372D6 PRIMARY KEY CLUSTERED ( ID_PROPLAST )
)

Триггеров нет.
Про RI константы не знаю, что за зверь ;)
prozaeck
Дата: 23.01.2009 02:23:15
Увеличил число обновляемых столбцов с двух до десяти.
Время выросло незначительно - на 0.03-0.07 секунды.
prozaeck
Дата: 23.01.2009 03:06:25
Senya_L,

План запроса:
StmtText
  |--Clustered Index Update(OBJECT:([GG3].[dbo].[T_PRO_PLAST].[PK__T_PRO_PLAST__7E6372D6]), SET:([T_PRO_PLAST].[PP_K]=[Expr1005], 
        [T_PRO_PLAST].[upsize_ts]=[Expr1006], 
        [T_PRO_PLAST].[POR_PP]=[Expr1004]))
       |--Top(1)
            |--Compute Scalar(DEFINE:([Expr1004]=Convert([@1]), 
                                                  [Expr1005]=Convert([@2]), 
                                                  [Expr1006]=gettimestamp(8)))
                 |--Clustered Index Seek(OBJECT:([GG3].[dbo].[T_PRO_PLAST].
PK__T_PRO_PLAST__7E6372D6]), SEEK:([T_PRO_PLAST].[ID_PROPLAST]=Convert([@3])) ORDERED FORWARD)

Это то что надо?
aleks2
Дата: 23.01.2009 06:26:48
>>2. В чем конкретно тормоз
Для UPDATE чаще всего тормоз в дисковой подсистеме, ибо писать приходится и в базу и в лог.
А то еще и индексы перестраивать, если обновленные поля участвуют в этих самых индексах...

РАДИКАЛЬНОЕ СРЕДСТВО - подумать на тему: а НУЖНО ЛИ РЕАЛЬНО такое обновление? Может стоит перепроектировать бизнес-логику?
ChA
Дата: 23.01.2009 08:43:29
prozaeck
Update делаю 3 тысячам ( будет 30-50 тысяч)
Все 3000 обновлений делаются в одной транзакции ? Или все 3000 по одной в очереди посылаются с клиента ?
prozaeck
Select этих же строк быстрее ~ 50 раз.
Сравните, сколько понадобится времени прочитать книгу и сколько - переписать её, даже если умеете печатать "вслепую".

prozaeck
1. Это и так очень быстро и ускорить в разы не реально?
Судя по плану из самого времени выполнения запроса выжать уже действительно ничего нельзя. Поиск по кластерному, обновление его не задевает, в смысле, не требует его перестройки. Так что вариантов маловато. По количеству записей(26000) практически все могут быть "подняты" в памяти, так что от дисковой подсистемы мало толку. Разве что диск с логами может подтормаживать. Но при выполнении в одной транзакции влияние этого фактора тоже может сильно уменьшится.

prozaeck
2. В чем конкретно тормоз

2. Если в запрос добавить
    from T_PRO_PLAST with(index(0)) 
время выполнения -12 секунд. Означает ли это, что индексирование работает на 100% и здесь ничего не выжать?

3. Если в запрос добавить
    from T_PRO_PLAST with(index(PK__T_PRO_PLAST__7E6372D6)) 
время выполнения - 2.8 секунды. Почему? Разве таким образом не указывается тот же самый индекс, что используется по умолчанию?
Потому что в первом варианте вы заставляете использовать полное сканирование индекса(scan), а во втором - используется точный поиск(seek). Указание with(index(1)) даст тот же эффект, что и второй вариант.

prozaeck
5. Есть ли способ у этого индекса поиграться с fill factor не создавая таблицу заново?
fill factor здесь абсолютно не при делах.

prozaeck
6. Замена UPDATE на DELETE и INSERT может помочь?
В данном случае - нет, а вот если бы обновление задевало само значение кластерного индекса, то не исключено.
tpg
Дата: 23.01.2009 08:55:57
Можно попробовать ещё покурить DBCC SHOWCONTIG и, возможно, пересоздание кластерного индекса.