4

我有一个包含几亿行数据的表。有一个字段称为EventId整数字段。

我有许多不同的视图,它们只会返回具有特定 EventId 的数据

如果我运行查询

SELECT TOP 1000 * FROM vw_MyView 

返回行需要 5 分钟。我需要向什么添加索引?当前在主表上有索引用于主键(clustered on LogId)和 non-clustered on EventId,因为每个视图的 where 子句中都使用了该索引。

我知道可以索引视图 - 我应该在视图中索引哪些字段?我应该只运行 DB Engine Tuning Wizard 并查看它的内容吗?

更新以下反馈

我的包含所有数据的主表符合以下模式

LogId (int) PK
EventId (int)
Param1 varchar(255)
Param2 varchar(255)
..
..
..
Param24 varchar(255)

每种事件类型都有不同的参数,因此主表中的通用字段名称。

我对每种类型的事件都有一个视图,其中主表中的 ParamX 字段通过视图获得了正确的字段名称。

因此,一个事件的视图将类似于

SELECT LogId, Param1 AS Name, Param2 AS Address1, Param3 AS Address2
WHERE EventId = 10

我试过查询

SELECT TOP 1000 LogId from vw_MyView 

而且效果很快。其他领域正在减慢速度,我认为这是由于索引不佳?

更新 2 - 更多信息

以前,每个事件的数据都存储在每个事件的表中。这意味着添加新事件需要为每个事件创建一个新表。

我将数据批量导入临时表,然后将其移至我的主表中。批量导入使其速度更快,但我担心拥有如此大的主表可能意味着查询它变得如此缓慢以至于无法使用。

数百万行数据超过 10 年左右,因此我可能会将前 8 年的数据移至另一个数据库以进行存档,以便仅保留最近的 2 年。

所以问题是我是继续使用不需要维护但可能需要大量索引的主表方法,还是回到每个事件都有一个表的原始方法?

感谢各位大侠的反馈,真的很感谢

4

3 回答 3

3

通常,视图包含的列多于满足许多不同查询所需的列,在这些查询中,直接针对相关表和列可能会更好地受益。(我在 2010 年写过关于这个的博客。)在你的情况下,我认为索引视图不会对你有帮助......你正在编写的查询只会扫描该索引而不是基表上的聚集索引(和由于您没有进行聚合,因此行数将相同,但页面可能更少)。我认为更好的解决方案是优化基础表上的索引。

我可能建议的索引应该极大地帮助您在视图中显示的事件 10 的查询:

CREATE NONCLUSTERED INDEX Index_ForViewOnEvent10 
ON dbo.MasterTable(LogID)
INCLUDE(Param1, Param2, Param3)
WHERE EventID = 10;

由于该索引涵盖了查询,并且由于过滤器大大减少了必须扫描的行数,因此这应该是一个显着的改进。

您可以尝试使用/不使用 INCLUDE 部分。从聚集索引中提取它们可能足够有效。但我认为以上将是最好的选择。

现在,不要在这里胡说八道——正如我在下面解释的那样,你并不总是想在一个表上抛出 100 个索引来完美地满足 100 个不同的查询——在满足查询和不让你的写入之间找到平衡成糖浆。


我将分享一些关于数据库引擎优化顾问 (DTA) 的内容。

这个巫师不是魔法。运行它并查看它所说的内容并没有什么坏处,但您不应该只接受它的所有建议并实施它们。使用此工具时,我建议几件事:

  • 确保以完整的工作量呈现它。如果您向它提供一个查询并告诉它根据使该查询执行得更好的因素来创建索引,那么它会在不考虑其他查询可能不会从此类索引中受益的情况下这样做,或者其他查询可能会从该索引中受益有这个或那个其他专栏。
  • 非常注意 DTA 将提供的重复项。它可能提供两个或三个索引,它们具有相同的四个前导键,而尾随键或 INCLUDE 列中只有一个差异。它还喜欢鼓励大量使用 INCLUDE 列,您也需要注意这一点。
  • 添加索引会增加 DML 执行的工作(插入/更新/删除),因此您还应该记住工作负载的这些部分。

DBSophic拥有比索引调优向导更好的工具——它们考虑了整个工作负载并且不提供冗余索引。Qure Analyzer 是免费的,并提供 Qure Optimizer 中可用功能的子集。

于 2012-05-18T12:29:51.740 回答
2

我认为您将Indexed ViewsViews混淆了。索引视图当然可以(必须)有索引,但这并不意味着您必须使用索引视图才能让 SQL Server 使用索引。如果它认为使用索引会更快,它将使用常规视图中基础表上存在的任何索引。

因此,首先检查您的视图的 SQL,并确定哪些索引可以帮助该查询更快地执行。如果您发布视图的 SQL,我们可能会提出一些想法。

此外,您的 select 语句不包含 ORDER BY 子句,因此它是一个非确定性查询。换句话说,即使数据没有改变,您在后续运行中也可能会得到不同的结果。

关于EventId列,您可以尝试为其添加索引,但这可能无济于事。这取决于该列中数据的基数。

于 2012-05-18T12:20:27.847 回答
0

您不应该在具有“数亿行数据”的表上创建索引视图。常规视图只是存储在数据库中的 SQL 语句,因此如果您运行 select * from your_view,sql server 只需更改your_view其选择。

如果要索引视图,则必须将数据持久化在数据库中,这意味着在数据库上制作索引列的物理副本。可以想象,如果您有这么多行,它将大大增加存储大小,特别是如果您将那个大表与其他表连接起来

于 2012-05-18T13:45:45.513 回答