I am unable to create clustered index on my view for a derived table.
Please help me to optimize my view where I can create an index as its my requirement to optimize. If indexing is not possible for my case please help me to write a faster view.
Here is my code:
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
I tried to add the index by this :
CREATE UNIQUE CLUSTERED INDEX IDX_VW_FGDOrderByMaxTimeAdded_ID
ON dbo.VW_FGDOrderByMaxTimeAdded (id);
but got error:
Msg 10109, Level 16, State 1, Line 1
Cannot create index on view "sharedmsdb-LIVE.dbo.VW_FGDOrderByMaxTimeAdded" because it references derived table "a" (defined by SELECT statement in FROM clause).
Consider removing the reference to the derived table or not indexing the view.
Execution Plan for Devart Answer :
<?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>
Variant #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
Variant #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
Variant #3 ... the long way - aggregated table:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.