Блокировка двух писателей. Реально ли разрулить?

Oblom

Добрый день!Есть две таблицы:
CREATE TABLE [dbo].[LowTable](
	[LowID] [int] NOT NULL,
	[Text] [nvarchar](<b>50</b>) NOT NULL,
	[UID] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_LowTable] PRIMARY KEY CLUSTERED 
(
	[LowID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[HighTable](
	[HighID] [int] NOT NULL,
	[LowID] [int] NOT NULL,
 CONSTRAINT [PK_HighTable] PRIMARY KEY CLUSTERED 
(
	[HighID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[HighTable] WITH CHECK ADD CONSTRAINT [FK_HighTable_LowTable] FOREIGN KEY([LowID])
REFERENCES [dbo].[LowTable] ([LowID])

ALTER TABLE [dbo].[HighTable] CHECK CONSTRAINT [FK_HighTable_LowTable]
Над таблицей LowTable выполняется апдейт, затрагивающий столбцы Text, UID и не затрагивающий LowID, например такой:
update LowTable
set Text='test_'+CAST(CAST(SUBSTRING(Text,<b>6</b>,LEN(Text)-<b>5</b>) AS int)-<b>2</b> AS NVARCHAR)
where ISNUMERIC(LEFT(CAST(UID as nvarchar(<b>36</b>)),<b>1</b>))=<b>1</b>
В этот же момент в таблицу HighTable вставляется запись, например:
insert into HighTable values(<b>2</b>,<b>1</b>)
Возникает блокировка, из-за того что таблица HighTable ссылается на LowTable по Foreign Key LowID.Первый апдейт выполняется очень долго, поэтому блокировка критична. Реально ли её разрулить, учитывая, что поле LowID в первом запросе не используется?Версионность включена.
16 ответов

Oblom

where ISNUMERIC(LEFT(CAST(UID as nvarchar(36)),1))=1 - это сканирование всей таблицыКонечно такая команда будет блокировать больше, чем надо


Oblom

Glory,проблема не в конкретном запросе, это просто пример. На боевом запросе на UID висит индекс и сканирование идет по нему, при этом под апдейт попадает 90% записей. Просто в боевой таблице 15 полей, по которым идет апдейт и в ней 500 тысяч записей, поэтому даже проиндексированная таблица апдейтится долго


Oblom

Glory,проблема не в конкретном запросе, это просто пример. На боевом запросе на UID висит индекс и сканирование идет по нему, при этом под апдейт попадает 90% записей. Просто в боевой таблице 15 полей, по которым идет апдейт и в ней 500 тысяч записей, поэтому даже проиндексированная таблица апдейтится долго
Проблема именно в конкретных запросахПотому что нельзя заблокировать меньше данных, чем выбирается запросом.


Oblom

Glory,то есть если основной запрос отрабатывает 22 секунды, то блокировка тоже будет длиться ровно 22 секунды? грустно.спасибо, буду ковырять запрос дальше, или бить его на кучу мелких, чтобы блокировки были чаще, но короче.


Oblom

С другой стороны, моим запросом блокируется 2 столбца: Text, UID. А второй запрос блокируется из-за третьего столбца LowID, который в первом запросе не участвует. То есть я как раз и хочу, чтобы заблокировались ровно те данные, которые выбираются, не включая столбец LowID


Oblom

Glory,то есть если основной запрос отрабатывает 22 секунды, то блокировка тоже будет длиться ровно 22 секунды? грустно.спасибо, буду ковырять запрос дальше, или бить его на кучу мелких, чтобы блокировки были чаще, но короче.
Для того, чтобы не блокировать другие коннекты, нужно не блокировать данные, которые им нужныА вы со своим where ISNUMERIC(LEFT(CAST(UID as nvarchar(36)),1))=1 ничего, кроме всей таблицы заблокировать просто не в состоянии


Oblom

Glory,согласен, к примеру подошел халатно.Тогда приближу запрос к реальному:
CREATE TABLE [dbo].[LowTable](
	[LowID] [int] NOT NULL,
	[Price] [decimal](<b>9</b>, <b>2</b>) NOT NULL,
	[Text] [nvarchar](<b>50</b>) NOT NULL,
	[UID] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_LowTable] PRIMARY KEY CLUSTERED 
(
	[LowID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [ix_lowtable] ON [dbo].[LowTable] 
(
	[UID] ASC
)
INCLUDE ( [Price],
[Text]) 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]

create table #t(UID uniqueidentifier, Price decimal(<b>9</b>,<b>2</b>), Text nvarchar(<b>50</b>))
insert into #t 
select UID, Price, Text from LowTable where LowID<=<b>700000</b> order by NEWID()

update LowTable
set 
	Text=#t.Text,
	Price=#t.Price
from LowTable lt
	inner join #t on lt.UID=#t.UID
	
drop table #t
вот план выполнения запроса:
(<b>700000</b> row(s) affected)
Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
-------------------- -------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ----------------------------------------------------------------------------------------------------------------------- ------------- ------------- ------------- ----------- ---------------- ----------------------------------------------------------------------------------------------------------------------------------- -------- ---------------------------------------------------------------- -------- ------------------
<b>700000</b> <b>1</b> insert into #t 
select UID, Price, Text from LowTable where LowID<=<b>700000</b> order by NEWID() <b>1</b> <b>1</b> <b>0</b> NULL NULL NULL NULL <b>699999</b>,<b>3</b> NULL NULL NULL <b>115</b>,<b>2121</b> NULL NULL INSERT <b>0</b> NULL
<b>700000</b> <b>1</b> |--Table Insert(OBJECT:([tempdb].[dbo].[#t]), SET:([tempdb].[dbo].[#t].[UID] = [Segment_Test].[dbo].[LowTable].[UID],[tempdb].[dbo].[#t].[Price] = [Segment_Test].[dbo].[LowTable].[Price],[tempdb].[dbo].[#t].[Text] = [Segment_Test].[dbo].[LowTable].[Text] 1 2 1 Table Insert Insert OBJECT:([tempdb].[dbo].[#t]), SET:([tempdb].[dbo].[#t].[UID] = [Segment_Test].[dbo].[LowTable].[UID],[tempdb].[dbo].[#t].[Price] = [Segment_Test].[dbo].[LowTable].[Price],[tempdb].[dbo].[#t].[Text] = [Segment_Test].[dbo].[LowTable].[Text]) NULL 699999,3 47,34668 0,6999993 9 115,2121 NULL NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Top(ROWCOUNT est 0) 1 3 2 Top Top TOP EXPRESSION:((0)) NULL 699999,3 0 0,06999993 82 67,16546 [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Sort(ORDER BY:([Expr1007] ASC)) 1 4 3 Sort Sort ORDER BY:([Expr1007] ASC) NULL 699999,3 0,01126126 62,38684 98 67,09546 [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Expr1007] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Compute Scalar(DEFINE:([Expr1007]=newid())) 1 5 4 Compute Scalar Compute Scalar DEFINE:([Expr1007]=newid()) [Expr1007]=newid() 699999,3 0 0,06999993 98 4,697355 [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Expr1007] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Clustered Index Seek(OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SEEK:([Segment_Test].[dbo].[LowTable].[LowID] <= (700000)) ORDERED FORWARD) 1 6 5 Clustered Index Seek Clustered Index Seek OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SEEK:([Segment_Test].[dbo].[LowTable].[LowID] <= (700000)) ORDERED FORWARD [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID] 699999,3 3,857199 0,7701562 82 4,627355 [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID] NULL PLAN_ROW 0 1

(<b>6</b> row(s) affected)



(<b>1</b> row(s) affected)

(<b>700000</b> row(s) affected)
Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
-------------------- -------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------- ------------- ------------- ----------- ---------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------- ---------------------------------------------------------------- -------- ------------------
<b>0</b> <b>1</b> update LowTable
set 
	Text=#t.Text,
	Price=#t.Price
from LowTable lt
	inner join #t on lt.UID=#t.UID <b>3</b> <b>1</b> <b>0</b> NULL NULL NULL NULL <b>900897</b>,<b>1</b> NULL NULL NULL <b>252</b>,<b>9279</b> NULL NULL UPDATE <b>0</b> NULL
<b>0</b> <b>1</b> |--Index Update(OBJECT:([Segment_Test].[dbo].[LowTable].[ix_lowtable]), SET:([LowID1018] = [Segment_Test].[dbo].[LowTable].[LowID],[Price1019] = [Segment_Test].[dbo].[LowTable].[Price],[Text1020] = [Segment_Test].[dbo].[LowTable].[Text],[UID1021] = [Segm 3 3 1 Index Update Update OBJECT:([Segment_Test].[dbo].[LowTable].[ix_lowtable]), SET:([LowID1018] = [Segment_Test].[dbo].[LowTable].[LowID],[Price1019] = [Segment_Test].[dbo].[LowTable].[Price],[Text1020] = [Segment_Test].[dbo].[LowTable].[Text],[UID1021] = [Segment_Test].[dbo].[L NULL 900897,1 40,58622 0,9008971 9 252,9279 NULL NULL PLAN_ROW 0 1
<b>0</b> <b>1</b> |--Sort(ORDER BY:([Segment_Test].[dbo].[LowTable].[UID] ASC, [Segment_Test].[dbo].[LowTable].[LowID] ASC, [Act1017] ASC)) 3 5 3 Sort Sort ORDER BY:([Segment_Test].[dbo].[LowTable].[UID] ASC, [Segment_Test].[dbo].[LowTable].[LowID] ASC, [Act1017] ASC) NULL 900897,1 0,01126126 81,79688 90 211,4408 [Segment_Test].[dbo].[LowTable].[LowID], [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Act1017] NULL PLAN_ROW 0 1
<b>0</b> <b>1</b> |--Filter(WHERE:(NOT [Expr1015])) 3 6 5 Filter Filter WHERE:(NOT [Expr1015]) NULL 900897,1 0 0,3803788 90 129,6326 [Segment_Test].[dbo].[LowTable].[LowID], [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Act1017] NULL PLAN_ROW 0 1
<b>1400000</b> <b>1</b> |--Split 3 7 6 Split Split NULL [Act1017] 1000997 0 0,7507476 91 129,2523 [Segment_Test].[dbo].[LowTable].[LowID], [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Expr1015], [Act1017] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Clustered Index Update(OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SET:([Segment_Test].[dbo].[LowTable].[Text] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Text]),[Segment_Test].[dbo].[LowTable].[Price] = RaiseIfNullUpdate( 3 8 7 Clustered Index Update Update OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SET:([Segment_Test].[dbo].[LowTable].[Text] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Text]),[Segment_Test].[dbo].[LowTable].[Price] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Price])) WITH ORDERED PREFE NULL 500498,4 25,14314 0,5004984 87 128,5015 [Segment_Test].[dbo].[LowTable].[LowID], [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Expr1015] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Compute Scalar(DEFINE:([Expr1015]=[Expr1015])) 3 9 8 Compute Scalar Compute Scalar DEFINE:([Expr1015]=[Expr1015]) [Expr1015]=[Expr1015] 500498,4 0 0,05004984 71 102,8579 [lt].[LowID], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text], [Expr1015], [Expr1025] NULL PLAN_ROW 0 1
<b>0</b> <b>0</b> |--Compute Scalar(DEFINE:([Expr1015]=CASE WHEN [Expr1010] AND [Expr1009] THEN (1) ELSE (0) END)) 3 11 9 Compute Scalar Compute Scalar DEFINE:([Expr1015]=CASE WHEN [Expr1010] AND [Expr1009] THEN (1) ELSE (0) END) [Expr1015]=CASE WHEN [Expr1010] AND [Expr1009] THEN (1) ELSE (0) END 500498,4 0 0,05004984 71 102,8579 [lt].[LowID], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text], [Expr1015] NULL PLAN_ROW 0 1
<b>0</b> <b>0</b> |--Compute Scalar(DEFINE:([Expr1009]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Text] as [lt].[Text] = [tempdb].[dbo].[#t].[Text] THEN (1) ELSE (0) END, [Expr1010]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Price] as [l 3 12 11 Compute Scalar Compute Scalar DEFINE:([Expr1009]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Text] as [lt].[Text] = [tempdb].[dbo].[#t].[Text] THEN (1) ELSE (0) END, [Expr1010]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Price] as [lt].[Price] = [tempdb].[dbo].[#t].[Price] THEN (1) ELSE [Expr1009]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Text] as [lt].[Text] = [tempdb].[dbo].[#t].[Text] THEN (1) ELSE (0) END, [Expr1010]=CASE WHEN [Segment_Test].[dbo].[LowTable].[Price] as [lt].[Price] = [tempdb].[dbo].[#t].[Price] THEN (1) ELSE (0) END 500498,4 0 0,05004984 71 102,8078 [lt].[LowID], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text], [Expr1009], [Expr1010] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Top(ROWCOUNT est 0) 3 13 12 Top Top TOP EXPRESSION:((0)) NULL 500498,4 0 0,05004984 127 102,7578 [lt].[LowID], [lt].[Price], [lt].[Text], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Sort(DISTINCT ORDER BY:([lt].[LowID] ASC)) 3 14 13 Sort Distinct Sort DISTINCT ORDER BY:([lt].[LowID] ASC) NULL 500498,4 0,01126126 43,49466 127 102,7077 [lt].[LowID], [lt].[Price], [lt].[Text], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Hash Match(Inner Join, HASH:([tempdb].[dbo].[#t].[UID])=([lt].[UID]), RESIDUAL:([tempdb].[dbo].[#t].[UID]=[Segment_Test].[dbo].[LowTable].[UID] as [lt].[UID])) 3 15 14 Hash Match Inner Join HASH:([tempdb].[dbo].[#t].[UID])=([lt].[UID]), RESIDUAL:([tempdb].[dbo].[#t].[UID]=[Segment_Test].[dbo].[LowTable].[UID] as [lt].[UID]) NULL 500498,4 0 48,81116 127 59,2018 [lt].[LowID], [lt].[Price], [lt].[Text], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text] NULL PLAN_ROW 0 1
<b>700000</b> <b>1</b> |--Table Scan(OBJECT:([tempdb].[dbo].[#t])) 3 16 15 Table Scan Table Scan OBJECT:([tempdb].[dbo].[#t]) [tempdb].[dbo].[#t].[UID], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text] 700000 3,579421 0,770157 82 4,349578 [tempdb].[dbo].[#t].[UID], [tempdb].[dbo].[#t].[Price], [tempdb].[dbo].[#t].[Text] NO STATS:([#t].[Price], [#t].[Text]) PLAN_ROW 0 1
<b>1000000</b> <b>1</b> |--Index Scan(OBJECT:([Segment_Test].[dbo].[LowTable].[ix_lowtable] AS [lt]), ORDERED FORWARD) 3 17 15 Index Scan Index Scan OBJECT:([Segment_Test].[dbo].[LowTable].[ix_lowtable] AS [lt]), ORDERED FORWARD [lt].[LowID], [lt].[Price], [lt].[Text], [lt].[UID] 1000000 4,940903 1,100157 86 6,04106 [lt].[LowID], [lt].[Price], [lt].[Text], [lt].[UID] NO STATS:([LowTable].[Price], [LowTable].[Text]) PLAN_ROW 0 1

(<b>14</b> row(s) affected)



(<b>1</b> row(s) affected)
,но всё равно тут присутствует строка
|--Clustered Index Update(OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SET:([Segment_Test].[dbo].[LowTable].[Text] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Text]),[Segment_Test].[dbo].[LowTable].[Price] = RaiseIfNullUpdate( 3 8 7 Clustered Index Update Update OBJECT:([Segment_Test].[dbo].[LowTable].[PK_LowTable]), SET:([Segment_Test].[dbo].[LowTable].[Text] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Text]),[Segment_Test].[dbo].[LowTable].[Price] = RaiseIfNullUpdate([tempdb].[dbo].[#t].[Price])) WITH ORDERED PREFE NULL 500498,4 25,14314 0,5004984 87 128,5015 [Segment_Test].[dbo].[LowTable].[LowID], [Segment_Test].[dbo].[LowTable].[Price], [Segment_Test].[dbo].[LowTable].[Text], [Segment_Test].[dbo].[LowTable].[UID], [Expr1015] NULL PLAN_ROW 0 1
которая блокирует кластерный индекс, что собственно и является проблемой. И совершенно непонятно, откуда всплывает этот апдейт кластерного индекса, который не участвует в запросе.


Oblom

которая блокирует кластерный индекс, что собственно и является проблемой.
Естественно, что измененные записи будут заблокированыю
И совершенно непонятно, откуда всплывает этот апдейт кластерного индекса, который не участвует в запросе.
И где же, по-вашему, тогда находятся данные, если не в кластерном индексе?


Oblom

Oblom,на самом деле вашей проблемой является другая строка:
Index Scan(OBJECT:([Segment_Test].[dbo].[LowTable].[ix_lowtable] AS [lt]), ORDERED FORWARD)
Эта строка приводит к навешиванию блокировки на всю таблицу.


Oblom

iljy,так насколько я понимаю, если мы говорим об апдейте 70-90% записей таблицы, то других вариантов собственно и нет? то есть он всё равно сваливается на блокировку таблицы?


Oblom

Oblom,укажите соединение явно - inner loop join. Станет медленнее, но блокировок меньше. Возможно придется еще явно указывать rowlock и запретить LOCK_ESCLATION.


Oblom

iljy,ни loop, ни rowlock не помог, как был Index Scan в плане, так и остался


Oblom

провел тест на апдейте одной записи, и выяснил, что если с primary key(столбец LowID) снять кластерность, проапдейтить столбец Price, блокировки столбца LowID при вставке в таблицу HighTable нет.Однако при апдейте всей таблицы это не проходит, вероятно потому, что он всё равно сваливается на блокировку всей таблицы, несмотря на хинт rowlock.Использование inner loop join замедляет запрос на слишком критичную величину.Собственно вопрос, как можно не свалится на tablock при апдейте значительной части таблицы?


Oblom

провел тест на апдейте одной записи, и выяснил, что если с primary key(столбец LowID) снять кластерность, проапдейтить столбец Price, блокировки столбца LowID при вставке в таблицу HighTable нет.Однако при апдейте всей таблицы это не проходит, вероятно потому, что он всё равно сваливается на блокировку всей таблицы, несмотря на хинт rowlock.Использование inner loop join замедляет запрос на слишком критичную величину.Собственно вопрос, как можно не свалится на tablock при апдейте значительной части таблицы?
не бывает блокировок столбцов. Блокируются строки. Не свалиться на блокировку таблицы поможет отключение LOCK_ESCALATION, я вам уже сказал.Вообще изначально ситуация глупая и говорит об огромных промахах в проектировании, ибо регулярный update 70-90% миллионной таблицы - это перебор.


Oblom

iljy,спасибо, вроде поборол.Помогли LOCK_ESCALATION и снятие кластерности с primary key.По поводу ошибок в проектировании - эта таблица в денормализованной базе созданной под определенный режим, а этот апдейт - синхронизация базы. Может это и ошибка в проектировании, но она обеспечивает нужную работу режима.


Oblom

iljy,спасибо, вроде поборол.Помогли LOCK_ESCALATION и снятие кластерности с primary key.По поводу ошибок в проектировании - эта таблица в денормализованной базе созданной под определенный режим, а этот апдейт - синхронизация базы. Может это и ошибка в проектировании, но она обеспечивает нужную работу режима.
Если это синхронизация - так делайте ее в моменты минимальной загрузки. а еще лучше - не изобретайте велосипед и воспользуйтесь стандартными механизмами, а именно - триггерами либо репликацией.