索引视图在没有 INNER JOIN 或子查询的情况下查找空引用

Posted

技术标签:

【中文标题】索引视图在没有 INNER JOIN 或子查询的情况下查找空引用【英文标题】:Indexed View looking for null references without INNER JOIN or Subquery 【发布时间】:2013-10-01 09:21:42 【问题描述】:

所以我有一个像这样的表结构的遗留数据库(简化)

Create Table Transaction

    TransactionId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    ReplacesTransactionId INT
    ..
    ..

所以我想创建一个索引视图,以便以下示例仅返回第二个角色(因为它替换了第一个角色)

Insert Into Transaction (TransactionId, ReplacesTransactionId, ..) Values (1,0 ..)
Insert Into Transaction (TransactionId, ReplacesTransactionId, ..) Values (2,1 ..)

有多种方法可以创建此查询,但我想创建一个索引视图,这意味着我不能使用子查询、左连接或例外。可以是一个示例查询(使用 LEFT JOIN)。

SELECT trans1.* FROM Transaction trans1 
LEFT JOIN Transaction trans2 on trans1.TransactionId = trans2.ReplacesTransactionId
Where trans2.TransacationId IS NULL

显然,我被数据库的结构所困扰,并希望使用这些数据来提高应用程序的性能。

有什么建议吗?

【问题讨论】:

如果您遇到一个合理的查询违反索引视图规则的问题,很可能查询的任何重写都会违反相同的规则或另一个同样糟糕的规则。我无法修复您显示的查询。 【参考方案1】:

您在这里拥有的本质上是一个分层数据集,您希望在其中预先遍历层次结构并将结果存储在索引视图中,但 AFAIK,索引视图不支持这一点。

另一方面,这可能不是实现提高性能这一更大目标的唯一方法。首先,最明显的问题:我们可以假设TransactionId 是聚集的并且ReplacesTransactionId 是索引的吗?如果没有,那将是我的前两个更改。如果索引已经很好,那么下一步就是查看左连接的查询计划,看看是否有任何问题。

一般来说(没有看到查询计划):一种可能的方法是尝试将您的 SELECT 语句转换为“覆盖查询”(请参阅​​https://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/)。这很可能需要以下组合:

减少 SELECT 语句中的列数(替换 SELECT *) 在 ReplacesTransactionId 上的索引中添加一些“包含”列(在 SSMS 中或使用 CREATE INDEX 的 INCLUDES 子句)。

祝你好运!

【讨论】:

非常感谢您的帮助。我开始意识到我试图实现的目标可能是不可能的。很高兴有人确认。 我有一个后续想法——即使你被结构困住了,你能创建一个额外的表吗?我想也许是这样,因为创建一个额外的视图是一种选择。如果是这样,请记住“索引视图”实际上只是一个内容自动管理的表。因此,您可以通过创建帮助表(如果您愿意,甚至可以像视图一样命名)然后使用触发器自动填充它来“滚动您自己的”。有点类似的例子,见***.com/a/19101016/2824445

以上是关于索引视图在没有 INNER JOIN 或子查询的情况下查找空引用的主要内容,如果未能解决你的问题,请参考以下文章

关于SQL 查询效率问题 left join 改成 inner join union

两个索引良好的表的单个 INNER JOIN 需要超过一分钟才能运行

sql left join 和 inner join 效率

使用昂贵的 INNER JOIN 优化 MySQL 查询

left joinright join和inner join

left joinright join和inner join