我无法在我的视图上为派生表创建聚簇索引。
请帮助我优化我的视图,我可以创建索引作为我的优化要求。如果我的情况下无法编制索引,请帮我写一个更快的视图。
这是我的代码:
ALTER VIEW [dbo].[VW_FGDOrderByMaxTimeAdded]
WITH SCHEMABINDING
AS
SELECT t.id,
t.Customer,
t.Scanner,
t.custType,
FDGOrder,
StatusID,
TimeAdded,
cntID,
empID,
effectChildren
FROM dbo.smsFDGOrder t
INNER JOIN dbo.smsFDGOrderStatus ON t.id = dbo.smsFDGOrderStatus.FDGOrder
INNER JOIN (
SELECT smsFDGOrder.id,
MAX(DISTINCT TimeAdded) AS MAX_TIME
FROM dbo.smsFDGOrder AS smsFDGOrder
INNER JOIN dbo.smsFDGOrderStatus ON smsFDGOrder.id = FDGOrder
GROUP BY smsFDGOrder.id
) a ON a.id = t.id
AND a.MAX_TIME = TimeAdded
我试图通过这个添加索引:
CREATE UNIQUE CLUSTERED INDEX IDX_VW_FGDOrderByMaxTimeAdded_ID
ON dbo.VW_FGDOrderByMaxTimeAdded (id);
但得到了错误:
Msg 10109,Level 16,State 1,Line 1
无法在视图“sharedmsdb-LIVE.dbo.VW_FGDOrderByMaxTimeAdded”上创建索引,因为它引用派生表“a”(由FROM子句中的SELECT语句定义)。
考虑删除对派生表的引用或不进行索引 观点。
Devart答案的执行计划:
<?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.5343.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementId="1" StatementText="CREATE /*UNIQUE*/ NONCLUSTERED INDEX ixd ON dbo.smsFDGOrderStatus (FDGOrder, TimeAdded DESC)
" StatementType="CREATE INDEX" RetrievedFromCache="false" />
</Statements>
</Batch>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementEstRows="72653.9" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="10.5795" StatementText="
SELECT t.id,
 t.Customer,
 t.Scanner,
 t.custType,
 s.FDGOrder,
 s.StatusID,
 s.TimeAdded,
 s.cntID,
 s.empID,
 s.effectChildren
FROM dbo.smsFDGOrder t
JOIN dbo.smsFDGOrderStatus s ON t.id = s.FDGOrder
JOIN (
 SELECT FDGOrder, MAX(TimeAdded) AS MAX_TIME
 FROM dbo.smsFDGOrderStatus
 GROUP BY FDGOrder
) a ON a.FDGOrder = s.FDGOrder
 AND a.MAX_TIME = TimeAdded" StatementType="SELECT" QueryHash="0x75C062BEC9148C5B" QueryPlanHash="0xF019E4D78D6C40" 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="NoParallelPlansInDesktopOrExpressEdition" CachedPlanSize="32" CompileTime="36" CompileCPU="36" CompileMemory="488">
<MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
<OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="102297" EstimatedPagesCached="7864" EstimatedAvailableDegreeOfParallelism="2" />
<RelOp AvgRowSize="49" EstimateCPU="0.317657" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="72653.9" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Merge Join" EstimatedTotalSubtreeCost="10.5795">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="ID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Customer" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Scanner" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="custType" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="StatusID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="TimeAdded" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="cntID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="empID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="effectChildren" />
</OutputList>
<Merge ManyToMany="false">
<InnerSideJoinColumns>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</InnerSideJoinColumns>
<OuterSideJoinColumns>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="ID" />
</OuterSideJoinColumns>
<Residual>
<ScalarOperator ScalarString="[sharedmsdb-LIVE].[dbo].[smsFDGOrder].[ID] as [t].[ID]=[sharedmsdb-LIVE].[dbo].[smsFDGOrderStatus].[FDGOrder]">
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="ID" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
</Residual>
<RelOp AvgRowSize="23" EstimateCPU="0.0798894" EstimateIO="0.193495" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="72484" LogicalOp="Clustered Index Scan" NodeId="1" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.273385" TableCardinality="72484">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="ID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Customer" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Scanner" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="custType" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="ID" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Customer" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="Scanner" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Alias="[t]" Column="custType" />
</DefinedValue>
</DefinedValues>
<Object Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrder]" Index="[PK_FDGOrder]" Alias="[t]" IndexKind="Clustered" />
</IndexScan>
</RelOp>
<RelOp AvgRowSize="36" EstimateCPU="1.67094" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="72654.8" LogicalOp="Inner Join" NodeId="2" Parallel="false" PhysicalOp="Merge Join" EstimatedTotalSubtreeCost="9.9885">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="StatusID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="TimeAdded" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="cntID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="empID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="effectChildren" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</OutputList>
<Merge ManyToMany="false">
<InnerSideJoinColumns>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
</InnerSideJoinColumns>
<OuterSideJoinColumns>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</OuterSideJoinColumns>
<Residual>
<ScalarOperator ScalarString="[sharedmsdb-LIVE].[dbo].[smsFDGOrderStatus].[FDGOrder]=[sharedmsdb-LIVE].[dbo].[smsFDGOrderStatus].[FDGOrder] as [s].[FDGOrder] AND [Expr1007]=[sharedmsdb-LIVE].[dbo].[smsFDGOrderStatus].[TimeAdded] as [s].[TimeAdded]">
<Logical Operation="AND">
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Column="Expr1007" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="TimeAdded" />
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
</Logical>
</ScalarOperator>
</Residual>
<RelOp AvgRowSize="19" EstimateCPU="0.445733" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="72440" LogicalOp="Aggregate" NodeId="3" Parallel="false" PhysicalOp="Stream Aggregate" EstimatedTotalSubtreeCost="2.57312">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
<ColumnReference Column="Expr1007" />
</OutputList>
<StreamAggregate>
<DefinedValues>
<DefinedValue>
<ColumnReference Column="Expr1007" />
<ScalarOperator ScalarString="MAX([sharedmsdb-LIVE].[dbo].[smsFDGOrderStatus].[TimeAdded])">
<Aggregate AggType="MAX" Distinct="false">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="TimeAdded" />
</Identifier>
</ScalarOperator>
</Aggregate>
</ScalarOperator>
</DefinedValue>
</DefinedValues>
<GroupBy>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</GroupBy>
<RelOp AvgRowSize="19" EstimateCPU="0.750931" EstimateIO="1.37646" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="682522" LogicalOp="Index Scan" NodeId="4" Parallel="false" PhysicalOp="Index Scan" EstimatedTotalSubtreeCost="2.12739" TableCardinality="682522">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="TimeAdded" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="FDGOrder" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Column="TimeAdded" />
</DefinedValue>
</DefinedValues>
<Object Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Index="[ixd]" IndexKind="NonClustered" />
</IndexScan>
</RelOp>
</StreamAggregate>
</RelOp>
<RelOp AvgRowSize="32" EstimateCPU="0.750931" EstimateIO="4.9935" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="682522" LogicalOp="Index Scan" NodeId="8" Parallel="false" PhysicalOp="Index Scan" EstimatedTotalSubtreeCost="5.74443" TableCardinality="682522">
<OutputList>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="StatusID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="TimeAdded" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="cntID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="empID" />
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="effectChildren" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="FDGOrder" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="StatusID" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="TimeAdded" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="cntID" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="empID" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Alias="[s]" Column="effectChildren" />
</DefinedValue>
</DefinedValues>
<Object Database="[sharedmsdb-LIVE]" Schema="[dbo]" Table="[smsFDGOrderStatus]" Index="[_dta_index_smsFDGOrderStatus_5_1938105945__K2_K3_K1_K4_5_6_7_8]" Alias="[s]" IndexKind="NonClustered" />
</IndexScan>
</RelOp>
</Merge>
</RelOp>
</Merge>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
答案 0 :(得分:0)
变体#1:
CREATE /*UNIQUE*/ NONCLUSTERED INDEX ix ON dbo.smsFDGOrderStatus (FDGOrder, TimeAdded DESC)
GO
SELECT t.id,
t.Customer,
t.Scanner,
t.custType,
s.FDGOrder,
s.StatusID,
s.TimeAdded,
s.cntID,
s.empID,
s.effectChildren
FROM dbo.smsFDGOrder t
JOIN dbo.smsFDGOrderStatus s ON t.id = s.FDGOrder
JOIN (
SELECT FDGOrder, MAX(TimeAdded) AS MAX_TIME
FROM dbo.smsFDGOrderStatus
GROUP BY FDGOrder
) a ON a.FDGOrder = s.FDGOrder
AND a.MAX_TIME = s.TimeAdded
变体#2:
CREATE /*UNIQUE*/ NONCLUSTERED INDEX ix2
ON dbo.smsFDGOrderStatus(FDGOrder, TimeAdded DESC)
INCLUDE (StatusID, cntID, empID, effectChildren)
GO
SELECT t.id,
t.Customer,
t.Scanner,
t.custType,
s.FDGOrder,
s.StatusID,
s.TimeAdded,
s.cntID,
s.empID,
s.effectChildren
FROM dbo.smsFDGOrder t
JOIN (
SELECT FDGOrder,
StatusID,
TimeAdded,
cntID,
empID,
effectChildren,
RowNum = ROW_NUMBER() OVER (PARTITION BY FDGOrder ORDER BY TimeAdded DESC)
FROM dbo.smsFDGOrderStatus
) t ON t.id = s.FDGOrder
AND t.RowNum = 1
变体#3 ......漫长的路 - 聚合表:
IF OBJECT_ID('dbo.smsFDGOrderStatus_Last', 'U') IS NOT NULL
DROP TABLE dbo.smsFDGOrderStatus_Last
GO
SELECT FDGOrder, MAX(TimeAdded) AS MAX_TIME
INTO dbo.smsFDGOrderStatus_Last
FROM dbo.smsFDGOrderStatus
GROUP BY FDGOrder
GO
CREATE UNIQUE CLUSTERED INDEX ix_l ON dbo.table_name (FDGOrder)
GO
CREATE /*UNIQUE*/ NONCLUSTERED INDEX ix2
ON dbo.smsFDGOrderStatus(FDGOrder, TimeAdded DESC)
INCLUDE (StatusID, cntID, empID, effectChildren)
GO
CREATE TRIGGER dbo.trg_ID
ON dbo.smsFDGOrderStatus
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
;WITH cte AS (
SELECT *
FROM dbo.smsFDGOrderStatus
WHERE FDGOrder IN (SELECT i.FDGOrder FROM INSERTED i)
)
MERGE cte t
USING (
SELECT FDGOrder, MAX(TimeAdded) AS MAX_TIME
FROM INSERTED
GROUP BY FDGOrder
) s ON s.ManufacturerName = t.ManufacturerString
WHEN MATCHED AND (t.MAX_TIME != s.MAX_TIME)
THEN
UPDATE SET MAX_TIME = s.MAX_TIME
WHEN NOT MATCHED BY TARGET
THEN
INSERT (FDGOrder, MAX_TIME)
VALUES (s.ManufacturerName, s.MAX_TIME);
END
GO
SELECT t.id,
t.Customer,
t.Scanner,
t.custType,
s.FDGOrder,
s.StatusID,
s.TimeAdded,
s.cntID,
s.empID,
s.effectChildren
FROM dbo.smsFDGOrder t
JOIN dbo.smsFDGOrderStatus s ON t.id = s.FDGOrder
JOIN dbo.smsFDGOrderStatus_Last a ON a.FDGOrder = s.FDGOrder AND a.MAX_TIME = s.TimeAdded