Хотя я не могу раскрыть информацию о реальных таблицах (если бы мог, я бы это сделал), вызывающих проблемы, описанные в моем предыдущем вопросе, я с нуля создал (не) рабочий пример, который воспроизводит точно (тип данных по данным тип, размер столбца по размеру столбца) проблема, с которой я сталкиваюсь. Поэтому я создал новую базу данных с именем «QueueTest» и запустил следующий скрипт:
CREATE TABLE Request
(
RequestID BIGINT PRIMARY KEY,
Priority TINYINT,
DateEntered DATETIME
)
CREATE TABLE Options
(
RequestIDRef BIGINT PRIMARY KEY,
SomeOptions NVARCHAR(MAX)
)
ALTER TABLE Options ADD
CONSTRAINT FK_REQUESTIDREF FOREIGN KEY ( RequestIDRef ) REFERENCES [Request] ( RequestID )
GO
INSERT INTO Request VALUES ( 1, 2, GETDATE() )
INSERT INTO Request VALUES ( 2, 1, GETDATE() )
INSERT INTO Request VALUES ( 3, 3, GETDATE() )
INSERT INTO Request VALUES ( 4, 2, GETDATE() )
INSERT INTO Options VALUES ( 1, 'Options1' )
INSERT INTO Options VALUES ( 2, 'Options2' )
INSERT INTO Options VALUES ( 3, 'Options3' )
INSERT INTO Options VALUES ( 4, 'Options4' )
CREATE NONCLUSTERED INDEX IX_OPTIONS_REQUESTIDREF ON [Options] ( RequestIDRef )
CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request] ( Priority , DateEntered ) INCLUDE ( RequestID )
После этого я открыл два новых запроса Query1
и Query2
и запустил следующие сценарии для имитации проблемы:
BEGIN TRANSACTION
SELECT TOP 2 RequestID FROM ( Request R WITH ( ROWLOCK , UPDLOCK , READPAST ) INNER JOIN Options O WITH ( ROWLOCK , UPDLOCK , READPAST ) ON ( R.RequestID = O.RequestIDRef ) ) ORDER BY Priority ASC , DateEntered ASC
WAITFOR DELAY '00:00:02.500'
COMMIT TRANSACTION
Результаты, которые я получил, были
Query1 | Query 2
2 |
1 |
пока я, конечно, ожидал
Query1 | Query 2
2 | 4
1 | 3
Итак, я предполагаю, что, хотя у меня есть индексы, описанные выше, Query1
все еще блокирует всю таблицу. Вот план выполнения для обоих запросов:
План выполнения
StmtText
-----------------------
SET SHOWPLAN_TEXT ON
(1 row(s) affected)
StmtText
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BEGIN TRANSACTION
SELECT TOP 2 RequestID FROM ( Request R WITH ( ROWLOCK , UPDLOCK , READPAST ) INNER JOIN Options O WITH ( ROWLOCK , UPDLOCK , READPAST ) ON ( R.RequestID = O.RequestIDRef ) ) ORDER BY Priority ASC , DateEntered ASC
(2 row(s) affected)
StmtText
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|--Top(TOP EXPRESSION:((2)))
|--Nested Loops(Inner Join, WHERE:([QueueTest].[dbo].[Options].[RequestIDRef] as [O].[RequestIDRef]=[QueueTest].[dbo].[Request].[RequestID] as [R].[RequestID]))
|--Index Scan(OBJECT:([QueueTest].[dbo].[Request].[IX_REQUEST_PRIORITY_DATEENTERED] AS [R]), ORDERED FORWARD)
|--Clustered Index Scan(OBJECT:([QueueTest].[dbo].[Options].[PK__Options__5366EEE80BC6C43E] AS [O]))
(4 row(s) affected)
StmtText
---------------------------------
WAITFOR DELAY '00:00:02.500'
COMMIT TRANSACTION
(2 row(s) affected)
Обратите внимание, что когда я выполнил оба запроса с SET SHOWPLAN_TEXT ON
, я думаю, что инструкция WAITFOR DELAY
не была соблюдена - фактически первый запрос завершился немедленно, поэтому, когда я запустил второй, он уже завершился. *
Что может быть причиной проблемы с блокировкой? Пожалуйста, помогите мне, так как я не могу понять это сам.
Редактировать: Обратите внимание, что я не могу создать вид с помощью инструкции SELECT TOP 2
. 2
здесь для иллюстрации, в то время как в реальной ситуации это параметр, передаваемый хранимой процедуре, которая затем запускает эту SELECT
. Обратите внимание, что при создании индексированного представления с использованием
SET QUOTED_IDENTIFIER ON
GO
ALTER VIEW TestView WITH SCHEMABINDING AS
SELECT RequestID , Priority , DateEntered FROM( dbo.Request R INNER JOIN dbo.Options O ON ( R.RequestID = O.RequestIDRef ) )
GO
CREATE UNIQUE CLUSTERED INDEX IX_TESTE_1 ON TestView ( RequestID )
CREATE NONCLUSTERED INDEX IX_TESTE_2 ON TestView ( Priority ASC , DateEntered ASC ) INCLUDE ( RequestID )
, а затем выбор из TestView WITH ( ROWLOCK , UPDLOCK , READPAST )
также не работал ни с, ни без предложения ORDER BY
.