我一直在研究使用索引视图来提高一些最常用的视图的性能。
然而,索引视图不支持非唯一聚集索引,这与数据库结构的其余部分设置的优先级略有不同。
例如,这是我们几个表的简化版本。
-Groups-
Group ID GroupName
-Users-
UserKey UserName FullName GroupID
Run Code Online (Sandbox Code Playgroud)
索引位于 Groups.GroupID(非集群)和 Users.GroupID(集群)上。聚集键位于用户表中的 GroupID 上,因为最常见的是将检索来自特定组的用户范围。显然每个组会有多个用户,所以这个聚集索引是非唯一的。
这让我有点不确定在索引我的视图(例如这个例子)时如何遵循这个优先级,因为我不能有一个非唯一的聚集索引。
ConsumableID ConsumableVariantID AllowThresholdOverwrite FullPath GroupID ManufacturerID Type ModelID
101 29 1 0.1.2.4. 4 3 3 2
Run Code Online (Sandbox Code Playgroud)
实际上,此视图上唯一始终唯一的值是 ConsumableID 列,因此在放置索引的位置方面我几乎没有选择。
当常规表允许时,为什么视图不允许非唯一聚集索引?
我正在努力在以下场景中设置索引视图,以便在没有两个聚集索引扫描的情况下执行以下查询。每当我为此查询创建索引视图然后使用它时,它似乎忽略了我放在它上面的任何索引:
-- +++ THE QUERY THAT I WANT TO IMPROVE PERFORMANCE-WISE +++
SELECT TOP 1 *
FROM dbo.TB_test1 t1
INNER JOIN dbo.TB_test2 t2 ON t1.PK_ID1 = t2.FK_ID1
ORDER BY t1.somethingelse1
,t2.somethingelse2;
GO
Run Code Online (Sandbox Code Playgroud)
表设置如下:
(在下面的脚本中也有一些行来生成测试数据,以防万一它有助于重现问题)
-- +++ TABLE SETUP +++
CREATE TABLE [dbo].[TB_test1]
(
[PK_ID1] [INT] IDENTITY(1, 1) NOT NULL
,[something1] VARCHAR(40) NOT NULL
,[somethingelse1] BIGINT NOT NULL
CONSTRAINT [PK_TB_test1] PRIMARY KEY CLUSTERED ( [PK_ID1] ASC )
);
GO
create TABLE [dbo].[TB_test2]
(
[PK_ID2] [INT] IDENTITY(1, …Run Code Online (Sandbox Code Playgroud)index sql-server-2008 sql-server materialized-view index-tuning
我有一张桌子和一个索引视图,就像
Create table mytable1 (ID int identity(1,1), Name nvarchar(100))
Create table mytable2 (ID int identity(1,1), Name nvarchar(100))
Create view myview
with schemabinding
as
select a.name, b.name
from mytable1 a
join mytable2 b on a.Id = b.Id
Run Code Online (Sandbox Code Playgroud)
现在,如果我运行以下查询
select a.name, b.name
from mytable1 a
join mytable2 b on a.Id = b.Id
Run Code Online (Sandbox Code Playgroud)
它不使用我的索引视图。是否有任何提示(或其他方式)可以强制 SQL Server 改用索引视图?
我有一个很大的系统,需要优化它。我无法更改所有 SQL 脚本以从视图而不是表中进行选择。我想创建索引视图并强制 SQL Server 从它们而不是表中获取数据。
我使用的是 SQL Server 2014 企业版。
物化视图(MV)日志可用于允许 MV 进行快速刷新,仅修改已更改的数据。但是,各种条件会阻止 MV 使用日志,因此需要完全刷新。Oracle 实现了原子完全刷新作为每条记录的删除和插入。即使最终没有对数据进行更改,它也会这样做。
有没有办法让这个复制在重做生成方面变得智能?MERGE 后跟 DELETE 需要查询源两次。批量收集数据以进行批量合并和删除是否值得?有没有更好的办法?
更新:
我探索了使用全局临时表作为暂存区。虽然他们使用的重做不到一半,但他们仍然使用了很多。
我有一个带有聚集索引和 2 个非聚集索引的表。现在,在我看来,我正在从我的表中选择所有内容
create view dbo.MyView
as
Select * from MyTable
Run Code Online (Sandbox Code Playgroud)
现在,当我在查询中使用这个视图时,我可以假设这个视图将利用在表上创建的索引。(即与Select * from MyTable 的工作方式相同)?或者我应该使用索引视图
补充问题
如果视图可以利用表索引,那么使用SELECT * FROM MyView Where SomeColumn = @someValue可能会严重影响性能(如果视图有大量数据,那么它在没有索引时会表现得像堆)。如何克服这个问题?除了使用 NOEXPAND(因为我使用的是企业版)
我想收集数据库中运行次数最多的查询的统计信息。
为此,我需要知道如何跟踪查询,以便我可以创建视图或物化视图来缓存最高运行查询的结果,因为我有一个大数据库。
我正在研究使用READPAST提示来减少我们应用程序财务子系统中的资源锁定。
这似乎是一个不错的方法,因为金融交易记录只会被添加,不会被更新或删除。唯一会被跳过的行是插入事务中的全新行;在事务提交之前,它们实际上不存在于外部世界。
但是,我注意到使用我已READPAST提示的索引视图的查询性能较差。比较查询计划,通过提示,查询优化器选择不使用索引视图,而是退回到将其视为常规视图。
我不确定为什么会这样;我想索引视图就像任何其他索引一样,因为键可以在操作期间被锁定,并且添加的READPAST工作方式类似。
SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0
Run Code Online (Sandbox Code Playgroud)
SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0
Run Code Online (Sandbox Code Playgroud)
添加NOEXPAND提示似乎也有效,但我有兴趣了解更多关于可能READPAST导致查询优化器首先做出该选择的原因(作为完整答案的一部分)。
performance sql-server hints materialized-view query-performance
我正在查看 PostgreSQL 文档,其中:
REFRESH MATERIALIZED VIEW 完全取代了物化视图的内容。旧内容被丢弃。
但是,从 9.5 开始,我相信有一种方法可以更新 MV,而无需重新生成所有数据。
我有你的基本标题/细节表(想想订单和订单细节)。标题表有一个标识列作为聚集键,详细信息有一个标题 id 和一个行号列作为聚集键。header id 是一个不断增加的标识值,行号也是一个递增的值。
我试图在细节上添加一个索引视图来聚合数据,所以我们不必在代码中或通过触发器来做这件事,在现有系统中有它自己的一组并发问题。
在我们开始对其进行负载测试之前,一切看起来和工作正常。预计表中将添加约 1500 条详细信息/秒(90,000 条/分钟)。
当一行插入到明细表时,索引视图也会更新。在插入过程中,索引视图上出现共享范围锁 (RangeS-U)。取的范围是下一个键的当前键,类似于在可序列化隔离级别下获取锁的方式。连接是在已提交读下设置的。当表中不存在“下一个”键时,似乎会出现瓶颈。在这种情况下,共享锁被用于 'infinity(ffffffff)' 键。
这基本上描述了我看到的行为,但没有提供任何解决方法。 https://www.brentozar.com/archive/2018/09/locks-taken-during-indexed-view-modifications/
在上述负载下,服务器无法跟上插入的速度,并且事情开始备份得非常快。600 个并发连接中有 500 个在给定时间被阻塞。对不断增加的键的聚合索引视图似乎无法满足我们的并发要求。
我们使用的是 SQL Server 2012 标准版,很快就会升级到 2019。
有什么方法可以改变索引视图上的这种锁定行为,或者这对我来说是徒劳的,在这种情况下,我需要走基于代码/触发器的聚合之路,还是我错过了什么?如果 2019 没有表现出对我有用的行为,因为数据库将在工作完成之前升级。
包含的脚本代表所涉及的表,但显然不是实际的表。使用它们可以重现该行为。
设置
if object_id(N'dbo.LockTest') is null
begin
create table dbo.LockTest
( LockTestID int not null primary key
, LockTestValue int null
);
insert into dbo.locktest values(1, 1), (2, 2), (3, 3), (7, 7), (8, 8);
end;
if object_id(N'dbo.LockTestDetails') is null
begin
create table dbo.LockTestDetails
( LockTestID int not null
, LineNumber …Run Code Online (Sandbox Code Playgroud) 每次在索引视图引用的基表中插入、更新或删除数据时,数据库引擎都会自动更新索引视图以反映更改。但是,我不太确定数据库引擎如何更新索引视图。它是否完全重新运行视图中的查询,或者是否使用更有效的方法仅更新相应的部分?
sql-server ×7
index ×2
postgresql ×2
view ×2
hints ×1
index-tuning ×1
locking ×1
oracle ×1
performance ×1