我有两个表,每个表大约500k行(并且正在增长)。插入/更新不断发生,有时每分钟100次。该系统在基本插入这些表时存在性能问题,即超时。我们调整了索引,并完成了通常的优化。但我想知道这两个表是否在5个视图中被引用并加入大量事实可能是有害的。我一直认为,也许是错误的,随着基础表的变化,引用它们的视图也会发生变化。因此,如果表格发生了这么大的变化,那么我们的系统可能会因为不断地进行追赶更新视图而不堪重负。
答案 0 :(得分:11)
除非他们是indexed views(你在问题中没有提到这一点),否则他们根本不会“更新”。
普通视图类似于C中的宏 - 它们只是隐藏较大表达式的一部分的便捷缩写。它们被扩展到任何引用它们的语句的解析树中,然后在使用时编译和优化整个树。
对于索引视图,您将在很大程度上正确 - 视图将作为执行基表中更改的同一事务的一部分进行维护。但是,已设计索引视图的规则,以便此更新活动不会产生太大的惩罚(可以维护它们而无需重新查询整个基表)。
答案 1 :(得分:4)
取决于:
1)如果未对视图编制索引,则会展开视图
-- View definition
CREATE VIEW Sales.v_SalesOrderDetail
AS
SELECT h.SalesOrderID, h.SalesOrderNumber, h.OrderDate,
d.SalesOrderDetailID, d.OrderQty, d.UnitPrice, d.LineTotal,
p.ProductID, p.Name AS ProductName, p.Color AS ProductColor
FROM Sales.SalesOrderHeader h
INNER JOIN Sales.SalesOrderDetail d ON h.SalesOrderID = d.SalesOrderID
INNER JOIN Production.Product p ON d.ProductID = p.ProductID
GO
-- View usage
SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName
FROM Sales.v_SalesOrderDetail v
WHERE v.ProductColor='Red';
GO
如果我们查看执行计划(SSMS:Ctrl + M),
然后我们将看到视图(FROM Sales.v_SalesOrderDetail v
)被扩展,服务器只查询两个表:Sales.SalesOrderDetail d
和Production.Product p
。此外,我们还可以看到Sales.SalesOrderHeader h
和Sales.SalesOrderDetail d
之间的联接是如何被删除的,因为:
SELECT
子句(SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName
)不包含Sales.SalesOrderHeader
表中的列,
有一个外键约束和
此FK约束是可信的。
2)如果视图已编入索引(意味着视图中已定义UNIQUE CLUSTERED INDEX
)并且SQL Server版本为enterprise,则视图可以扩展为或不。如果版本<>企业然后索引视图被扩展。我们可以使用NOEXPAND
提示强制服务器不扩展 [索引]视图:
-- View definition
CREATE VIEW Sales.v_SalesOrderDetail2
WITH SCHEMABINDING
AS
SELECT h.SalesOrderID, h.SalesOrderNumber, h.OrderDate,
d.SalesOrderDetailID, d.OrderQty, d.UnitPrice, d.LineTotal,
p.ProductID, p.Name AS ProductName, p.Color AS ProductColor
FROM Sales.SalesOrderHeader h
INNER JOIN Sales.SalesOrderDetail d ON h.SalesOrderID = d.SalesOrderID
INNER JOIN Production.Product p ON d.ProductID = p.ProductID
GO
-- Defining the UNIQUE CLUSTERED INDEX
CREATE UNIQUE CLUSTERED INDEX PK_v_SalesOrderDetail2
ON Sales.v_SalesOrderDetail2 (SalesOrderDetailID);
GO
-- View usage
SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName
FROM Sales.v_SalesOrderDetail2 v WITH (NOEXPAND)
WHERE v.ProductColor='Red';
GO
在这种情况下,我们可以看到执行计划
包括Clustered Index Scan PK_v_SalesOrderDetail2
运算符。因此,它使用在第二个视图上定义的索引。
答案 2 :(得分:2)
SQLServer视图不会被缓存,因此每次请求视图时都会执行查询
答案 3 :(得分:-1)
调整索引很好但是可能值得考虑更新这些索引的统计信息的频率和时间。此外,使用缓冲表来保存插入,然后可以每隔5或10分钟将其作为批量操作插入或者适合您的系统的任何内容可能有所帮助(将它放在单独的物理磁盘上将是一个好主意。)这样做会使90%的时间选择速度要快得多,而其他10%的时间选择速度要差得多。