简体   繁体   English

SQL Server如何处理视图后面的表上的索引?

[英]How does SQL Server treat indexes on a table behind a view?

So I'm trying to understand how SQL Server makes use of indexes on tables behind views. 所以我试图了解SQL Server如何在视图后面的表上使用索引。 Here's the scenario: Table A has a composite clustered index on fields 1 & 2 and a nonclustered index on fields 3 & 4. 下面是场景:表A在字段1和2上具有复合聚簇索引,在字段3和4上具有非聚簇索引。

View A is written against Table A to filter out additional fields, but fields 1-4 are part of the view. 视图A针对表A编写以过滤掉其他字段,但字段1-4是视图的一部分。 So we write a query that joins the view to another table on the nonclustered index fields. 因此,我们编写一个查询,将视图连接到非聚簇索引字段上的另一个表。

The resulting query plan hits Table A with a clustered index scan (instead of the expected nonclustered index seek). 生成的查询计划使用聚簇索引扫描(而不是预期的非聚簇索引搜索)命中表A. However, if we replace the view in the FROM clause with the table, the query plan then hits the nonclustered index and we get the index seek we expected. 但是,如果我们用表替换FROM子句中的视图,则查询计划会访问非聚簇索引,并获得我们预期的索引搜索。

Shouldn't the SQL engine make use of the index on the table the view is constructed on? SQL引擎是否应该使用构建视图的表上的索引? Since it doesn't, why not? 既然没有,为什么不呢?

When you're thinking of non-materialized views and optimizations -- think of them like this: 当您考虑非物化视图和优化时 - 想象它们是这样的:

The engine is "cutting and pasting" the view text into every query you perform. 引擎将视图文本“剪切并粘贴”到您执行的每个查询中。

OK, that's not exactly 100% true, but it's probably the most helpful way to think of what to expect in terms of performance. 好吧,这不是100%真实,但它可能是最有用的方式来考虑性能方面的预期。

Views can be tricky, though. 但是,观点可能很棘手。 People tend to think that just because a column is in a view, that it means something significant when it comes to query performance. 人们倾向于认为仅仅因为列在视图中,这意味着在查询性能方面有重要意义。 The truth is, if the query which uses your view doesn't include a set of columns, it can be "optimized away". 事实是,如果使用您的视图的查询不包含一组列,则可以“优化掉”。 So if you were to SELECT every column from your base tables in your view, and then you were to only select one or two columns when you actually use the view, the query will be optimized considering only those two columns you select. 因此,如果您要在视图中从基表中选择每一列,然后在实际使用视图时只选择一列或两列,则只考虑您选择的那两列,将优化查询。

Another consequence of this is that you can use views to very aggressively flatten out table structures. 这样做的另一个后果是您可以使用视图来非常积极地平整表结构。 So let's say for example I have the following schema: 所以,比方说,我有以下架构:

Widget
-------
ID (UNIQUE)
Name
Price
WidgetTypeID (FK to WidgetType.ID)

WidgetType
----------
ID (UNIQUE)
Name

vw_Widgets
----------
SELECT w.ID, w.Name, w.Price, w.WidgetTypeID, wt.Name AS TypeName
FROM Widgets w
LEFT JOIN WidgetType wt
   ON wt.ID = w.WidgetTypeID;

Note the LEFT JOIN in the view definition. 请注意视图定义中的LEFT JOIN。 If you were to simply SELECT Name, Price FROM vw_Widgets , you'd notice that WidgetType wasn't even involved in the query plan! 如果您只是简单地SELECT Name, Price FROM vw_Widgets ,您会注意到WidgetType甚至没有参与查询计划! It's completely optimized away! 它完全被优化了! This works with LEFT JOINS across unique columns because the optimizer knows that since WidgetType's ID is UNIQUE, it won't generate any duplicate rows from the join. 这适用于跨唯一列的LEFT JOINS,因为优化器知道由于WidgetType的ID是UNIQUE,因此它不会从连接生成任何重复的行。 And since there's a FK, you know that you can leave the join as a LEFT join because you'll always have a corresponding row. 由于存在FK,您知道可以将连接保留为LEFT连接,因为您将始终拥有相应的行。

So the moral of the story here with views is that the columns you select at the end of the day are the ones that matter, not the ones in the view. 因此,带有观点的故事的寓意是,您在一天结束时选择的列是重要的列,而不是视图中的列。 Views aren't optimized when they're created -- they're optimized when they're used . 视图在创建时不会进行优化 - 它们在使用时会进行优化。

Your question isn't really about views 你的问题不是关于观点

Your question is actually more generic -- why can't you use the NC index? 你的问题实际上更通用 - 为什么你不能使用NC索引? I can't tell you really because I can't see your schema or your specific query, but suffice it to say that at a certain point, the optimizer sees that the cost of looking up the additional fields outweighs what it would have cost to scan the table (because seeks are expensive) and ignores your nonclustered index. 我无法告诉你真的因为我看不到你的架构或你的具体查询,但足以说明在某个时刻,优化器会发现查找其他字段的成本超过了它的成本。扫描表(因为搜索是昂贵的)并忽略您的非聚集索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM