Tạo một hướng dẫn kế hoạch để lưu trữ kết quả CTE (bộ đệm lười biếng)


19

Tôi thường tạo hướng dẫn kế hoạch bằng cách trước tiên xây dựng một truy vấn sử dụng đúng kế hoạch và sao chép nó sang truy vấn tương tự không có. Tuy nhiên, điều đó đôi khi khó khăn, đặc biệt nếu truy vấn không hoàn toàn giống nhau. Cách đúng đắn để tạo hướng dẫn kế hoạch từ đầu là gì?

SQLKiwi đã đề cập đến việc lên kế hoạch trong SSIS, có cách nào hoặc công cụ hữu ích để hỗ trợ đưa ra một kế hoạch tốt cho SQL Server không?

Ví dụ cụ thể trong câu hỏi là CTE: SQLFiddle này

with cte(guid,other) as (
  select newid(),1 union all
  select newid(),2 union all
  select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;

bất kỳ cách để làm cho kết quả đưa ra chính xác 3 biệt guids và không nhiều? Tôi hy vọng có thể trả lời tốt hơn các câu hỏi trong tương lai bằng cách bao gồm các hướng dẫn kế hoạch với các truy vấn loại CTE được tham chiếu nhiều lần để vượt qua một số yêu cầu CTE của SQL Server.


Câu trả lời:


14

Có cách nào để đưa ra kết quả với chính xác 3 hướng dẫn riêng biệt và không còn nữa không? Tôi hy vọng có thể trả lời tốt hơn các câu hỏi trong tương lai bằng cách bao gồm các hướng dẫn kế hoạch với các truy vấn loại CTE được tham chiếu nhiều lần để vượt qua một số yêu cầu CTE của SQL Server.

Không phải hôm nay. Các biểu thức bảng chung không đệ quy (CTE) được coi là các định nghĩa khung nhìn nội tuyến và được mở rộng thành cây truy vấn logic tại mỗi nơi chúng được tham chiếu (giống như các định nghĩa khung nhìn thông thường) trước khi tối ưu hóa. Cây logic cho truy vấn của bạn là:

LogOp_OrderByCOL: Union1007 ASC COL: Union1015 ASC 
    LogOp_Project COL: Union1006 COL: Union1007 COL: Union1014 COL: Union1015
        LogOp_Join
            LogOp_ViewAnchor
                LogOp_UnionAll
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const

            LogOp_ViewAnchor
                LogOp_UnionAll
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const
                    LogOp_Project ScaOp_Intrinsic newid, ScaOp_Const

Lưu ý hai View View Neo và sáu lệnh gọi đến hàm nội tại newidtrước khi bắt đầu tối ưu hóa. Tuy nhiên, nhiều người cho rằng trình tối ưu hóa phải có khả năng xác định rằng các cây con mở rộng ban đầu chỉ là một đối tượng được tham chiếu và đơn giản hóa theo. Cũng đã có một số yêu cầu kết nối để cho phép cụ thể hóa rõ ràng CTE hoặc bảng dẫn xuất.

Một triển khai tổng quát hơn sẽ có trình tối ưu hóa xem xét cụ thể hóa các biểu thức phổ biến tùy ý để cải thiện hiệu suất ( CASEvới một truy vấn con là một ví dụ khác mà các vấn đề có thể xảy ra ngày hôm nay). Microsoft Research đã xuất bản một bài báo (PDF) vào năm 2007, mặc dù cho đến nay nó vẫn chưa được thực hiện. Hiện tại, chúng tôi bị giới hạn trong việc cụ thể hóa rõ ràng bằng cách sử dụng những thứ như biến bảng và bảng tạm thời.

SQLKiwi đã đề cập đến việc lên kế hoạch trong SSIS, có cách nào hoặc công cụ hữu ích để hỗ trợ đưa ra một kế hoạch tốt cho SQL Server không?

Đây chỉ là mơ tưởng của tôi, và vượt xa ý tưởng sửa đổi hướng dẫn kế hoạch. Về nguyên tắc, có thể viết một công cụ để thao tác trực tiếp với kế hoạch XML, nhưng nếu không có công cụ tối ưu hóa cụ thể bằng cách sử dụng công cụ này có thể sẽ là một trải nghiệm khó chịu cho người dùng (và nhà phát triển nghĩ về nó).

Trong bối cảnh cụ thể của câu hỏi này, một công cụ như vậy vẫn không thể cụ thể hóa nội dung CTE theo cách mà nhiều người tiêu dùng có thể sử dụng (để cung cấp cả hai đầu vào cho tham gia chéo trong trường hợp này). Trình tối ưu hóa và công cụ thực thi hỗ trợ các cuộn nhiều người tiêu dùng, nhưng chỉ cho các mục đích cụ thể - không ai trong số đó có thể được thực hiện để áp dụng cho ví dụ cụ thể này.

Mặc dù tôi không chắc chắn, tôi có linh cảm khá mạnh mẽ rằng RelOps có thể được theo dõi (Nested Loop, Lazy Spool) ngay cả khi truy vấn không hoàn toàn giống như kế hoạch - ví dụ: nếu bạn đã thêm 4 và 5 vào CTE , nó vẫn tiếp tục sử dụng cùng một kế hoạch (dường như - đã được thử nghiệm trên SQL Server 2012 RTM Express).

Có một lượng linh hoạt hợp lý ở đây. Hình dạng rộng của kế hoạch XML được sử dụng để hướng dẫn tìm kiếm kế hoạch cuối cùng (mặc dù nhiều thuộc tính bị bỏ qua hoàn toàn, ví dụ như loại phân vùng trên các trao đổi) và các quy tắc tìm kiếm thông thường cũng được nới lỏng đáng kể. Ví dụ, việc cắt tỉa sớm các lựa chọn thay thế dựa trên các cân nhắc về chi phí bị vô hiệu hóa, việc giới thiệu rõ ràng các phép nối chéo được cho phép và các thao tác vô hướng bị bỏ qua.

Có quá nhiều chi tiết để đi sâu, nhưng vị trí của Bộ lọc và Tính toán vô hướng không thể bị ép buộc và các vị từ của biểu mẫu column = valueđược khái quát hóa để một kế hoạch có chứa X = 1hoặc X = @Xcó thể được áp dụng cho truy vấn có chứa X = 502hoặcX = @Y . Sự linh hoạt đặc biệt này có thể giúp rất nhiều trong việc tìm kiếm một kế hoạch tự nhiên để buộc.

Trong ví dụ cụ thể, liên tục All All luôn có thể được triển khai dưới dạng Quét liên tục; số lượng đầu vào cho Liên minh Tất cả không thành vấn đề.


3

Không có cách nào (phiên bản SQL Server cho đến năm 2012) để sử dụng lại một ống chỉ cho cả hai lần xuất hiện của CTE. Chi tiết có thể được tìm thấy trong câu trả lời của SQLKiwi. Dưới đây là hai cách để cụ thể hóa CTE hai lần, điều này không thể tránh khỏi đối với bản chất của truy vấn. Cả hai tùy chọn đều dẫn đến số lượng hướng dẫn riêng biệt là 6.

Liên kết từ bình luận của Martin đến trang của Quassnoi trên blog về kế hoạch hướng dẫn CTE là một phần cảm hứng cho câu hỏi này. Nó mô tả một cách để cụ thể hóa CTE cho mục đích của truy vấn con tương quan, chỉ được tham chiếu một lần mặc dù mối tương quan có thể khiến nó được đánh giá nhiều lần. Điều đó không áp dụng cho truy vấn trong câu hỏi.

Cách 1 - Hướng dẫn kế hoạch

Lấy gợi ý từ câu trả lời của SQLKiwi, tôi đã giảm hướng dẫn xuống mức tối thiểu vẫn sẽ thực hiện công việc, ví dụ: các ConstantScannút chỉ liệt kê 2 toán tử vô hướng có thể mở rộng đủ đến bất kỳ số nào.

;with cte(guid,other) as (
  select newid(),1 union all
  select newid(),2 union all
  select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other
OPTION(USE PLAN
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.2" Build="11.0.2100.60" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="1600" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.0444433" StatementText="with cte(guid,other) as (&#xD;&#xA;  select newid(),1 union all&#xD;&#xA;  select newid(),2 union all&#xD;&#xA;  select newid(),3&#xD;&#xA;select a.guid, a.other, b.guid guidb, b.other otherb&#xD;&#xA;from cte a&#xD;&#xA;cross join cte b&#xD;&#xA;order by a.other, b.other;&#xD;&#xA;" StatementType="SELECT" QueryHash="0x43D93EF17C8E55DD" QueryPlanHash="0xF8E3B336792D84" RetrievedFromCache="true">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan NonParallelPlanReason="EstimatedDOPIsOne" CachedPlanSize="96" CompileTime="13" CompileCPU="13" CompileMemory="1152">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="157240" EstimatedPagesCached="1420" EstimatedAvailableDegreeOfParallelism="1" />
            <RelOp AvgRowSize="47" EstimateCPU="0.006688" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1600" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0444433">
              <OutputList>
                <ColumnReference Column="Union1163" />
              </OutputList>
              <Warnings NoJoinPredicate="true" />
              <NestedLoops Optimized="false">
                <RelOp AvgRowSize="27" EstimateCPU="0.000432115" EstimateIO="0.0112613" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Sort" NodeId="1" Parallel="false" PhysicalOp="Sort" EstimatedTotalSubtreeCost="0.0117335">
                  <OutputList>
                    <ColumnReference Column="Union1080" />
                    <ColumnReference Column="Union1081" />
                  </OutputList>
                  <MemoryFractions Input="0" Output="0" />
                  <Sort Distinct="false">
                    <OrderBy>
                      <OrderByColumn Ascending="true">
                        <ColumnReference Column="Union1081" />
                      </OrderByColumn>
                    </OrderBy>
                    <RelOp AvgRowSize="27" EstimateCPU="4.0157E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Constant Scan" NodeId="2" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.0157E-05">
                      <OutputList>
                        <ColumnReference Column="Union1080" />
                        <ColumnReference Column="Union1081" />
                      </OutputList>
                      <ConstantScan>
                        <Values>
                          <Row>
                            <ScalarOperator ScalarString="newid()">
                              <Intrinsic FunctionName="newid" />
                            </ScalarOperator>
                            <ScalarOperator ScalarString="(1)">
                              <Const ConstValue="(1)" />
                            </ScalarOperator>
                          </Row>
                          <Row>
                            <ScalarOperator ScalarString="newid()">
                              <Intrinsic FunctionName="newid" />
                            </ScalarOperator>
                            <ScalarOperator ScalarString="(2)">
                              <Const ConstValue="(2)" />
                            </ScalarOperator>
                          </Row>
                        </Values>
                      </ConstantScan>
                    </RelOp>
                  </Sort>
                </RelOp>
                <RelOp AvgRowSize="27" EstimateCPU="0.0001074" EstimateIO="0.01" EstimateRebinds="0" EstimateRewinds="39" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Lazy Spool" NodeId="83" Parallel="false" PhysicalOp="Table Spool" EstimatedTotalSubtreeCost="0.0260217">
                  <OutputList>
                    <ColumnReference Column="Union1162" />
                    <ColumnReference Column="Union1163" />
                  </OutputList>
                  <Spool>
                    <RelOp AvgRowSize="27" EstimateCPU="0.000432115" EstimateIO="0.0112613" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Sort" NodeId="84" Parallel="false" PhysicalOp="Sort" EstimatedTotalSubtreeCost="0.0117335">
                      <OutputList>
                        <ColumnReference Column="Union1162" />
                        <ColumnReference Column="Union1163" />
                      </OutputList>
                      <MemoryFractions Input="0" Output="0" />
                      <Sort Distinct="false">
                        <OrderBy>
                          <OrderByColumn Ascending="true">
                            <ColumnReference Column="Union1163" />
                          </OrderByColumn>
                        </OrderBy>
                        <RelOp AvgRowSize="27" EstimateCPU="4.0157E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Constant Scan" NodeId="85" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.0157E-05">
                          <OutputList>
                            <ColumnReference Column="Union1162" />
                            <ColumnReference Column="Union1163" />
                          </OutputList>
                          <ConstantScan>
                            <Values>
                              <Row>
                                <ScalarOperator ScalarString="newid()">
                                  <Intrinsic FunctionName="newid" />
                                </ScalarOperator>
                                <ScalarOperator ScalarString="(1)">
                                  <Const ConstValue="(1)" />
                                </ScalarOperator>
                              </Row>
                              <Row>
                                <ScalarOperator ScalarString="newid()">
                                  <Intrinsic FunctionName="newid" />
                                </ScalarOperator>
                                <ScalarOperator ScalarString="(2)">
                                  <Const ConstValue="(2)" />
                                </ScalarOperator>
                              </Row>
                            </Values>
                          </ConstantScan>
                        </RelOp>
                      </Sort>
                    </RelOp>
                  </Spool>
                </RelOp>
              </NestedLoops>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>'
);

Tùy chọn 2 - Quét từ xa

Bằng cách tăng chi phí của truy vấn và giới thiệu Remote Scan, kết quả được cụ thể hóa.

with cte(guid,other) as (
  select *
  from OPENQUERY([TESTSQL\V2012], '
  select newid(),1 union all
  select newid(),2 union all
  select newid(),3') x)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;

2

Nói một cách nghiêm túc, bạn không thể cắt giảm các kế hoạch thực hiện xml từ đầu. Tạo chúng bằng SSIS là khoa học viễn tưởng. Vâng, tất cả đều là XML, nhưng chúng đến từ các vũ trụ khác nhau. Nhìn vào blog của Paul về chủ đề đó , anh ấy nói "nhiều theo cách SSIS cho phép ..." để bạn có thể hiểu nhầm? Tôi không nghĩ anh ấy nói "sử dụng SSIS để tạo kế hoạch" mà là "sẽ không tuyệt vời khi có thể tạo kế hoạch bằng giao diện kéo và thả như SSIS". Có thể, đối với một truy vấn rất đơn giản, bạn có thể quản lý điều này, nhưng nó rất khó, thậm chí có thể lãng phí thời gian. Công việc bận rộn bạn có thể nói.

Nếu tôi đang tạo một kế hoạch cho gợi ý SỬ DỤNG KẾ HOẠCH hoặc hướng dẫn kế hoạch, tôi có một vài cách tiếp cận. Ví dụ: tôi có thể xóa các bản ghi khỏi các bảng (ví dụ: trên một bản sao của db) để tác động đến các số liệu thống kê và khuyến khích trình tối ưu hóa đưa ra quyết định khác. Tôi cũng đã sử dụng các biến bảng thay vì tất cả các bảng trong truy vấn để trình tối ưu hóa nghĩ rằng mỗi bảng chứa 1 bản ghi. Sau đó, trong kế hoạch được tạo, thay thế tất cả các biến bảng bằng tên bảng gốc và hoán đổi nó thành kế hoạch. Một tùy chọn khác là sử dụng tùy chọn VỚI STATS_STREAM của CẬP NHẬT THỐNG KÊ để giả mạo số liệu thống kê, đây là phương pháp được sử dụng khi sao chép các bản sao cơ sở dữ liệu chỉ thống kê, ví dụ

UPDATE STATISTICS 
    [dbo].[yourTable]([PK_yourTable]) 
WITH 
    STATS_STREAM = 0x0100etc, 
    ROWCOUNT = 10000, 
    PAGECOUNT = 93

Tôi đã dành một chút thời gian mày mò với các kế hoạch thực hiện xml trong quá khứ và tôi đã thấy rằng cuối cùng, SQL chỉ đi "Tôi không sử dụng điều đó" và chạy truy vấn theo cách nào nó muốn.

Đối với ví dụ cụ thể của bạn, tôi chắc chắn rằng bạn biết rằng bạn có thể sử dụng bộ hàng 3 hoặc TOP 3 trong truy vấn để có kết quả đó, nhưng tôi đoán đó không phải là quan điểm của bạn. Các đúng câu trả lời sẽ thực sự là: sử dụng một bảng temp. Tôi sẽ tuyên bố rằng :) Không phải là một câu trả lời đúng sẽ là "dành hàng giờ thậm chí hàng ngày để cắt giảm kế hoạch thực thi XML tùy chỉnh của bạn, nơi bạn cố gắng để trình tối ưu hóa thực hiện một bộ đệm lười biếng cho CTE mà thậm chí có thể không hoạt động, trông sẽ rất thông minh nhưng cũng không thể duy trì ".

Không cố gắng để không gây trở ngại ở đó, chỉ là ý kiến ​​của tôi - hy vọng rằng sẽ giúp.


Nghiêm túc mà nói, các kế hoạch XML là không thể biết được?!, Tôi nghĩ đó là toàn bộ vấn đề? Nếu họ không hợp lệ thì nên ném.
crokusek

Tôi đã đề cập đến sự kiện Kế hoạch không thành công.
wBob

2

bất kỳ cách ...

Cuối cùng, trong SQL 2016 CTP 3.0, có một cách, loại :)

Sử dụng cờ theo dõi và Sự kiện mở rộng như chi tiết của Dmitry Pilugin tại đây , bạn có thể (hơi tùy tiện) đưa ra ba hướng dẫn độc đáo từ các giai đoạn trung gian của việc thực hiện truy vấn.

NB Mã này KHÔNG dành cho sản xuất hoặc sử dụng nghiêm túc liên quan đến kế hoạch CTE, chỉ đơn giản là một cái nhìn nhẹ nhàng về một cờ theo dõi mới và một cách làm khác:

-- Configure the XEvents session; with ring buffer target so we can collect it
CREATE EVENT SESSION [query_trace_column_values] ON SERVER 
ADD EVENT sqlserver.query_trace_column_values
ADD TARGET package0.ring_buffer( SET max_memory = 2048 )
WITH ( MAX_MEMORY = 4096 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY = 30 SECONDS, MAX_EVENT_SIZE = 0 KB, MEMORY_PARTITION_MODE = NONE, TRACK_CAUSALITY = OFF , STARTUP_STATE = OFF )
GO

-- Start the session
ALTER EVENT SESSION [query_trace_column_values] ON SERVER
STATE = START;
GO

-- Run the query, including traceflag
DBCC TRACEON(2486);
SET STATISTICS XML ON;
GO

-- Original query
;with cte(guid,other) as (
  select newid(),1 union all
  select newid(),2 union all
  select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other
option ( recompile )
go

SET STATISTICS XML OFF;
DBCC TRACEOFF(2486);
GO

DECLARE @target_data XML

SELECT @target_data = CAST( target_data AS XML )
FROM sys.dm_xe_sessions AS s 
    INNER JOIN sys.dm_xe_session_targets AS t ON t.event_session_address = s.address
WHERE s.name = 'query_trace_column_values'


--SELECT @target_data td

-- Arbitrarily fish out 3 unique guids from intermediate stage of the query as collected by XEvent session
;WITH cte AS
(
SELECT
    n.c.value('(data[@name = "row_id"]/value/text())[1]', 'int') row_id,
    n.c.value('(data[@name = "column_value"]/value/text())[1]', 'char(36)') [guid]
FROM @target_data.nodes('//event[data[@name="column_id"]/value[. = 1]][data[@name="row_number"]/value[. < 4]][data[@name="node_name"]/value[. = "Nested Loops"]]') n(c)
)
SELECT *
FROM cte a
    CROSS JOIN cte b
GO

-- Stop the session
ALTER EVENT SESSION [query_trace_column_values] ON SERVER
STATE = STOP;
GO

-- Drop the session
IF EXISTS ( select * from sys.server_event_sessions where name = 'query_trace_column_values' )
DROP EVENT SESSION [query_trace_column_values] ON SERVER 
GO

Đã thử nghiệm trên phiên bản (CTP3.2) - 13.0.900.73 (x64), chỉ để cho vui.


1

Tôi đã tìm thấy dấu vết 8649 (kế hoạch song song lực lượng) gây ra hành vi này cho cột hướng dẫn bên trái trong các phiên bản 2008, R2 và 2012 của tôi. Tôi không cần sử dụng cờ trên SQL 2005 khi CTE hoạt động chính xác. Tôi đã thử sử dụng gói được tạo trong SQL 2005 trong các trường hợp cao hơn nhưng nó sẽ không xác nhận.

with cte(guid,other) as (
  select newid(),1 union all
  select newid(),2 union all
  select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other
option ( querytraceon 8649 )

Sử dụng gợi ý, sử dụng hướng dẫn kế hoạch bao gồm gợi ý hoặc sử dụng gói được tạo bởi truy vấn với gợi ý trên trong KẾ HOẠCH SỬ DỤNG, v.v ... đều hoạt động. cte newid


Cảm ơn vì đã thử lại. Truy vấn không có vẻ khác biệt dù có hoặc không có cờ theo dõi đó vào năm 2008/2012. Không thực sự chắc chắn liệu đó là phiên bản SQL Server của tôi hay những gì bạn đang cố gắng hiển thị. Tôi vẫn thấy 18 hướng dẫn. Bạn thấy gì?
孔夫子

3 hướng dẫn riêng biệt ở phía bên trái (cột hướng dẫn), mỗi lần lặp lại ba lần. 9 hướng dẫn độc đáo ở phía bên tay phải (cột hướng dẫn), vì vậy ít nhất bit bên trái đang hành xử theo cách bạn muốn lol. Tôi đã thêm một hình ảnh vào câu trả lời khác để hy vọng làm rõ một chút. Những bước nhỏ. Tôi cũng cần lưu ý trong SQL 2005, tôi nhận được 6 hướng dẫn duy nhất, 3 ở bên trái, 3 ở bên phải.
wBob

Cũng chỉ cần lưu ý rằng việc loại bỏ 'tất cả' cũng nhận được 6 hướng dẫn duy nhất, 3 mỗi bên.
wBob

Có thể làm cho dấu vết không hoạt động bằng cách có máy chủ maxdop 1.
wBob
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.