2011-06-20 37 views
5

Tôi có hai bảng TableATableB có thông tin tôi muốn truy xuất và cập nhật đồng thời. Khi tôi sử dụngINNER JOIN và khóa

SELECT TOP 2 SomeFieldA 
FROM TableA WITH (ROWLOCK , UPDLOCK , READPAST) 

mọi thứ hoạt động tốt và Quy trình 1 nhìn thấy, các hàng 3 và 4. Đây là hành vi mong đợi. Ngoài ra, khi tôi thực hiện EXEC sp_lock tôi chỉ thấy hai mục nhập KEY. Tuy nhiên, khi tôi thay đổi tuyên bố thành

SELECT TOP 2 SomeFieldA 
FROM TableA WITH (ROWLOCK , UPDLOCK , READPAST) 
INNER JOIN 
Table B WITH (ROWLOCK , UPDLOCK , READPAST) 
ON TableA.ID = TableB.IDRef` 

quy trình đầu tiên nhìn thấy hàng 1 và 2, nhưng quy trình 2 không thấy gì cả. Thực hiện sp_lock cho thấy rằng bây giờ tất cả các hàng đã bị chặn. Tại sao chuyện này đang xảy ra?

Chỉnh sửa: Kế hoạch Thực hiện:

<?xml version="1.0" encoding="utf-16"?> 
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1" Build="10.50.1617.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"> 
    <BatchSequence> 
    <Batch> 
     <Statements> 
     <StmtSimple StatementCompId="2" StatementEstRows="2" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.00670141" StatementText="SELECT TOP 2 * FROM Request R WITH (ROWLOCK , UPDLOCK , READPAST) INNER JOIN Options O WITH (ROWLOCK , UPDLOCK , READPAST) ON (R.RequestID = O.RequestID)&#xD;&#xA;&#xD;" StatementType="SELECT" QueryHash="0xA35BE09F9DD52334" QueryPlanHash="0x95BEDE8C14AB4C68"> 
      <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" /> 
      <QueryPlan DegreeOfParallelism="1" CachedPlanSize="16" CompileTime="3" CompileCPU="3" CompileMemory="160"> 
      <RelOp AvgRowSize="58" EstimateCPU="2E-07" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2" LogicalOp="Top" NodeId="0" Parallel="false" PhysicalOp="Top" EstimatedTotalSubtreeCost="0.00670141"> 
       <OutputList> 
       <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="RequestID" /> 
       <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="DateEntered" /> 
       <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="Priority" /> 
       <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="RequestID" /> 
       <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="SomeOptions" /> 
       </OutputList> 
       <RunTimeInformation> 
       <RunTimeCountersPerThread Thread="0" ActualRows="2" ActualEndOfScans="1" ActualExecutions="1" /> 
       </RunTimeInformation> 
       <Top RowCount="false" IsPercent="false" WithTies="false"> 
       <TopExpression> 
        <ScalarOperator ScalarString="(2)"> 
        <Const ConstValue="(2)" /> 
        </ScalarOperator> 
       </TopExpression> 
       <RelOp AvgRowSize="58" EstimateCPU="7.524E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2" LogicalOp="Inner Join" NodeId="1" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.00670121"> 
        <OutputList> 
        <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="RequestID" /> 
        <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="DateEntered" /> 
        <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="Priority" /> 
        <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="RequestID" /> 
        <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="SomeOptions" /> 
        </OutputList> 
        <RunTimeInformation> 
        <RunTimeCountersPerThread Thread="0" ActualRows="2" ActualEndOfScans="0" ActualExecutions="1" /> 
        </RunTimeInformation> 
        <NestedLoops Optimized="false"> 
        <Predicate> 
         <ScalarOperator ScalarString="[TestDatabase].[dbo].[Options].[RequestID] as [O].[RequestID]=[TestDatabase].[dbo].[Request].[RequestID] as [R].[RequestID]"> 
         <Compare CompareOp="EQ"> 
          <ScalarOperator> 
          <Identifier> 
           <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="RequestID" /> 
          </Identifier> 
          </ScalarOperator> 
          <ScalarOperator> 
          <Identifier> 
           <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="RequestID" /> 
          </Identifier> 
          </ScalarOperator> 
         </Compare> 
         </ScalarOperator> 
        </Predicate> 
        <RelOp AvgRowSize="45" EstimateCPU="0.0001603" EstimateIO="0.003125" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2" LogicalOp="Clustered Index Scan" NodeId="2" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.0032842" TableCardinality="3"> 
         <OutputList> 
         <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="RequestID" /> 
         <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="SomeOptions" /> 
         </OutputList> 
         <RunTimeInformation> 
         <RunTimeCountersPerThread Thread="0" ActualRows="2" ActualEndOfScans="0" ActualExecutions="1" /> 
         </RunTimeInformation> 
         <IndexScan Ordered="false" ForcedIndex="false" NoExpandHint="false"> 
         <DefinedValues> 
          <DefinedValue> 
          <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="RequestID" /> 
          </DefinedValue> 
          <DefinedValue> 
          <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Alias="[O]" Column="SomeOptions" /> 
          </DefinedValue> 
         </DefinedValues> 
         <Object Database="[TestDatabase]" Schema="[dbo]" Table="[Options]" Index="[PK__Options__33A8519A1DE57479]" Alias="[O]" IndexKind="Clustered" /> 
         </IndexScan> 
        </RelOp> 
        <RelOp AvgRowSize="20" EstimateCPU="8.51E-05" EstimateIO="0.0032035" EstimateRebinds="0" EstimateRewinds="1.33333" EstimateRows="6" LogicalOp="Table Scan" NodeId="3" Parallel="false" PhysicalOp="Table Scan" EstimatedTotalSubtreeCost="0.00340207" TableCardinality="6"> 
         <OutputList> 
         <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="RequestID" /> 
         <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="DateEntered" /> 
         <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="Priority" /> 
         </OutputList> 
         <RunTimeInformation> 
         <RunTimeCountersPerThread Thread="0" ActualRows="8" ActualEndOfScans="1" ActualExecutions="2" /> 
         </RunTimeInformation> 
         <TableScan Ordered="false" ForcedIndex="false" NoExpandHint="false"> 
         <DefinedValues> 
          <DefinedValue> 
          <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="RequestID" /> 
          </DefinedValue> 
          <DefinedValue> 
          <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="DateEntered" /> 
          </DefinedValue> 
          <DefinedValue> 
          <ColumnReference Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" Column="Priority" /> 
          </DefinedValue> 
         </DefinedValues> 
         <Object Database="[TestDatabase]" Schema="[dbo]" Table="[Request]" Alias="[R]" IndexKind="Heap" /> 
         </TableScan> 
        </RelOp> 
        </NestedLoops> 
       </RelOp> 
       </Top> 
      </RelOp> 
      </QueryPlan> 
     </StmtSimple> 
     </Statements> 
    </Batch> 
    </BatchSequence> 
</ShowPlanXML> 

SQL:

CREATE TABLE Request 
(
    RequestID INT PRIMARY KEY, 
    Priority INT, 
    DateEntered DATETIME 
) 

CREATE TABLE Options 
(
    RequestIDRef INT 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, 'a') 
INSERT INTO Options VALUES (2, 'b') 
INSERT INTO Options VALUES (3, 'c') 
INSERT INTO Options VALUES (4, 'd') 

CREATE NONCLUSTERED INDEX IX_REQUESTIDREF ON [Options] (RequestIDRef) 
CREATE NONCLUSTERED INDEX IX_PRIORITY_DATEENTERED ON [Request] (Priority , DateEntered) INCLUDE (RequestID) 

Bây giờ,

BEGIN TRANSACTION 

SELECT TOP 2 * FROM [Request] WITH (ROWLOCK , UPDLOCK , READPAST) INNER JOIN [Options] WITH (ROWLOCK , UPDLOCK , READPAST) ON (Request.RequestID = Options.RequestIDRef) ORDER BY Priority, DateEntered 

WAITFOR DELAY '00:00:02.5' 

COMMIT TRANSACTION 

trên Query1 trả 2 và 1, như mong đợi, nhưng trên Query2 nó trả về không có gì. Tuy nhiên, nếu tôi xóa INNER JOIN và bảng thứ hai, nó hoạt động và trả về (2,1) trong Query1 và (3,4) trong Query2.

+0

Có bao nhiêu hàng trong mỗi bảng? –

+0

Bạn có thể thêm kế hoạch truy vấn không? Và dữ liệu thực tế? Và chỉ mục? – gbn

+0

er ... kế hoạch văn bản, không phải XML xin vui lòng – gbn

Trả lời

4

Về mặt logic, sản phẩm Descartes của A và B bị giới hạn ở giao lộ hoặc các hàng phù hợp.

Để tìm các hàng phù hợp này, TableA.ID và TableB.IDRef được xem xét. Yêu cầu quét bảng trên ít nhất một trong các bảng nếu không có chỉ mục. Vì vậy, tất cả các hàng đều bị khóa để quét

Vì vậy, cả TableA.ID và TableB.IDRef cần có chỉ mục. Tôi nghi ngờ rằng TableA.ID đã có PK nhưng TableB.IDRef thì không.

TOP được áp dụng sau BTW

Nó tương tự như câu trả lời của tôi ở đây, nơi có TOP là không có ORDER BY và không có chỉ mục: ORDER BY and WITH(ROWLOCK, UPDLOCK, READPAST). Nếu bạn đã thêm ORDER BY vào truy vấn thứ nhất, thì quy trình thứ 2 sẽ không thấy bất kỳ điều gì nhiều khả năng nhất.

Chỉnh sửa: để cập nhật, CHỌN * sẽ làm mất hiệu lực chỉ mục và quét: các chỉ mục không được sử dụng nhiều với SELECT * vì chúng không bao gồm

+0

Xin chào gbn, và cảm ơn một lần nữa. Nhưng nó vẫn không hoạt động. Vui lòng lưu ý chỉnh sửa của tôi. –

Các vấn đề liên quan