我想加快对视图的访问速度,并在其上放置了索引。不幸的是,这并没有被使用,尽管对我来说应该使用它似乎是合乎逻辑且显而易见的。有人能告诉我我做错了什么吗?
CREATE VIEW dbo.PickingInfoTEST WITH SCHEMABINDING AS
SELECT
ccs.ID_ChargeCarrier,
ccs.ID_Storage,
sp.ID_PlantArea,
pa.ID_Plant,
p.CompanyNo,
CAST(s.Description1 AS INT) AS PickingStorage,
s.Description2 AS TargetCountry,
COUNT_BIG(*) AS Commonness
FROM dbo.ChargeCarrier_Storage ccs
INNER JOIN dbo.Storage s ON s.ID = ccs.ID_Storage
INNER JOIN dbo.StoragePlace sp ON sp.ID = s.ID
INNER JOIN dbo.PlantArea pa ON pa.ID = sp.ID_PlantArea
INNER JOIN dbo.Plant p ON p.ID = pa.ID_Plant
WHERE s.ID_StorageType = 1
GROUP BY
ccs.ID_ChargeCarrier,
ccs.ID_Storage,
sp.ID_PlantArea,
pa.ID_Plant,
p.CompanyNo,
CAST(s.Description1 AS INT),
s.Description2
GO
CREATE UNIQUE CLUSTERED INDEX UQX_OnePickingStoragePerCarrier
ON dbo.PickingInfoTEST (ID_ChargeCarrier)
GO
CREATE UNIQUE INDEX IX_ChargeCarrier_OriginalStorage
ON dbo.PickingInfoTEST (ID_ChargeCarrier DESC) INCLUDE (ID_Storage)
GO
SELECT ID_ChargeCarrier
,ID_Storage
FROM dbo.PickingInfoTEST
WHERE ID_ChargeCarrier between 1234 and 5678
我希望代码块末尾的
SELECT
语句从 IX_ChargeCarrier_OriginalStorage
加载缓存值。它运行视图的代码。
视图的第一个索引必须是唯一的聚集索引。如果您那里没有其他索引,您肯定会看到该索引默认为集群。由于行估计和统计信息以及其他因素,优化器不会总是发现最适合查询的索引。由于这现在是一个聚集索引,您可以编写一个查询来直接从该索引中进行选择。
问题是默认情况下,SQL Server 会在您的查询中将视图扩展到其定义。然后它将尝试匹配索引,其中可能包括您的索引视图。
这有时会失败,尤其是对于像这样复杂的视图。 为了防止这种情况发生,并且出于other reasons,你应该几乎总是在索引视图上使用
WITH (NOEXPAND)
提示。
SELECT ID_ChargeCarrier
,ID_Storage
FROM dbo.PickingInfoTEST WITH (NOEXPAND)
WHERE ID_ChargeCarrier between 1234 and 5678;
在极少数情况下您可能不想使用此提示,例如您可能会删除索引,在这种情况下查询将失败。另请参阅在某些情况下,在索引视图上使用 (noexpand) 是不可取的吗?。但在大多数情况下你应该使用它。
正如其他人所说,降序索引几乎完全没有意义。
此外,您应该从
CAST
中删除GROUP BY
,因为它会导致不必要的排序(如果主键已经分组,优化器可以计算出不需要排序)。
...
GROUP BY
ccs.ID_ChargeCarrier,
ccs.ID_Storage,
sp.ID_PlantArea,
pa.ID_Plant,
p.CompanyNo,
s.Description1,
s.Description2