从视图中删除子查询以使其成为索引视图

Posted

技术标签:

【中文标题】从视图中删除子查询以使其成为索引视图【英文标题】:remove subquery from view to make it Indexed view 【发布时间】:2013-01-21 08:30:35 【问题描述】:

我想为全文搜索创建一个索引视图。

我面临子查询的唯一问题,因为索引视图不允许子查询。

下面是我的查询

ALTER VIEW [dbo].[Demo] with SCHEMABINDING  AS
select distinct a.ID,a.Title, a.Description ,b.Name as Recipe, c.Name as Taste , d.Name as CuisineType,
STUFF((SELECT ',' + Name FROM dbo.Ingredients where ID in (select IngredientID from dbo.listingIngredients 
where listingid = a.ID ) FOR XML PATH('')), 1, 1, '') as Ingredients
from dbo.Listing as a 
inner join dbo.RecipeType b on a.RecipeTypeID = b.ID
inner join dbo.taste c on a.tasteID = c.ID
inner join dbo.CuisineType d on a.CuisineTypeID = d.ID
inner join dbo.listingIngredients e on a.ID = e.listingID
GO

我使用子查询使用 STUFF 从成分表中获取成分作为连接字符串。

有人可以告诉我如何删除这个子查询并将成分作为满足的字符串。

请告诉我

问候 男子气概

【问题讨论】:

必须满足多个restrictions 才能使视图可索引。我的经验法则是 - 如果您的查询当前违反了其中一个限制,那么任何重写它的尝试都会遇到另一个限制。这些限制不是随意决定的——数据库引擎(通常)没有像样的方法来找到一种方法来维护一个破坏它们的索引。 我别无选择,因为对于全文搜索,我们需要索引视图..:(..请告诉我是否还有其他选择..除了全文搜索。 .我看到的唯一选择是动态SQL ...:( 唯一明显的转变是完全消除分组行为,每个成分只有一行。但是,一旦您走了这么远,就不清楚为什么对原始表进行全文索引是不够的。 如果我没有分组行为,那么会有重复,你是否建议重复很好..我应该在业务逻辑层中避免它们??... 我不能只有单一的成分,因为食品清单总是有多种成分..会有一个主要成分,其余所有子成分...... 【参考方案1】:

查询的 XML 部分会导致问题,即使您确实设法删除了子选择。

但是,一切都没有丢失。您可以将视图重写为可以索引的部分和更便宜但不能索引的另一部分。例如,你可以这样写:

ALTER VIEW [dbo].[Demo_Part] with SCHEMABINDING  AS
select a.ID,a.Title
, a.Description 
, b.Name as Recipe
, c.Name as Taste 
, d.Name as CuisineType
, e.name
from dbo.Listing as a 
inner join dbo.RecipeType b on a.RecipeTypeID = b.ID
inner join dbo.taste c on a.tasteID = c.ID
inner join dbo.CuisineType d on a.CuisineTypeID = d.ID
inner join dbo.listingIngredients e on a.ID = e.listingID
GROUP BY a.ID,a.Title
, a.Description 
, b.Name as Recipe
, c.Name as Taste 
, d.Name as CuisineType
, e.name

根据您的数据模型,您甚至可能不需要分组依据。这个视图可以被索引

然后编写另一个未编入索引但替换原始视图的视图

CREATE VIEW [dbo].[Demo]
SELECT ...
 STUFF (...)
FROM [dbo].[Demo_Part]

作为一个元答案,我要补充一点,如果您需要为这样的视图编制索引(并使用 DISTINCT),那么您的数据建模师很可能在数据模型上犯了一个很大的错误,或者您的数据访问代码是非常低效。这一切听起来都像是你在努力解决糟糕的编码和建模实践。

【讨论】:

以上是关于从视图中删除子查询以使其成为索引视图的主要内容,如果未能解决你的问题,请参考以下文章

关系数据库标准语言SQL02

带有子查询的 MySQL 视图

联合分组子查询视图事务python操作mysql索引

如何避免此子查询并创建索引视图?

12W学习笔记——独立子查询,更新,删除,建立视图

视图序列索引