5

我有两个表,每个表大约有 500k 行(并且还在增长)。这些不断发生插入/更新,有时每分钟 100 次。系统在基本插入这些表时存在性能问题,即超时。我们已经调整了索引,并进行了通常的优化。但我想知道这两个表在 5 个视图中被大量连接引用的事实是否可能是有害的。我一直认为,也许是错误的,随着基础表的变化,引用它们的视图也会发生变化。因此,如果表格变化如此之大,那么我们的系统可能会因为不得不不断地追赶更新视图而不堪重负。

4

4 回答 4

12

除非它们是索引视图(您在问题中没有提到这一点),否则它们根本不会“更新”。

普通视图类似于 C 中的宏——它们只是隐藏较大表达式的一部分的便捷简写。它们被扩展为引用它们的任何语句的解析树,然后在使用点编译和优化整个树。


对于索引视图,您在很大程度上是正确的 - 视图作为在基表中执行更改的同一事务的一部分进行维护。但是,索引视图的规则已经过设计,因此此更新活动不应招致太大的损失(无需重新查询整个基表即可维护它们)。

于 2013-02-11T15:28:37.987 回答
5

这取决于:

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 dProduction.Product p。此外,我们可以看到和之间的连接是如何Sales.SalesOrderHeader hSales.SalesOrderDetail d删除的,因为:

  • SELECT子句 ( SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName) 不包括表中的列Sales.SalesOrderHeader

  • 在这两个表之间有一个外键约束和

  • 这个 FK 约束是可信的。

2)如果视图被索引(意味着视图上有UNIQUE CLUSTERED INDEX定义)并且SQL Server版本是企业版,那么视图可以扩展或不扩展。如果 edition <> enterprise 则展开索引视图。我们可以通过使用提示强制服务器不展开[indexed] 视图: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操作符。因此,它使用在第二个视图上定义的索引。

请注意:SQL Server 错误索引视图 + MERGE

于 2013-02-11T16:10:21.847 回答
4

SQLServer 视图没有缓存,因此每次请求视图时都会执行查询

于 2013-02-11T15:11:22.930 回答
-1

调整索引很好,但可能值得考虑更新这些索引的统计信息的频率和时间。此外,使用缓冲表来保存插入,然后可以每隔 5 或 10 分钟或任何适合您的系统的批量操作插入这些插入可能会有所帮助(将其放在单独的物理磁盘上是个好主意。)这样做会使在 90% 的时间里选择快得多,在其他 10% 的时间里不会比当前差多少。

于 2016-06-08T10:25:35.657 回答