虽然我无法透露有关真实表格的信息(如果我可以,但我会)导致上一个问题中描述的问题,我从头开始构建了一个(非)工作示例,它准确地再现了数据类型 - 类型,列大小按列大小)我面临的问题。所以我创建了一个名为“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
子句。
答案 0 :(得分:1)
你有一个“聚集索引扫描”和一个“索引扫描”,它阻止了两个表中的所有行正如我在之前的回答中所说的那样。
同样来自之前的答案:
最后,索引IX_REQUEST_PRIORITY_DATEENTERED没有JOIN条件。这可能会删除其中一个扫描
如果你不听上面的“查看”位,那么试试这两个
CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request]
(RequestID , Priority , DateEntered )
CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request]
(Priority , DateEntered , RequestID )