0

有问题的表是供应商软件在我们网络上使用的数据库的一部分。该表包含有关文件的元数据。表的架构如下

Metadata 
ResultID (PK, int, not null) 
MappedFieldname (char(50), not null) 
Fieldname (PK, char(50), not null) 
Fieldvalue (text, null)

ResultID 和 Fieldname 上有一个聚集索引。该表通常包含数百万行(在一种情况下,它包含 5 亿行)。该表由 24 个工作人员填充,每个工作人员在“处理”数据时运行 4 个线程。这会导致许多非顺序插入。稍后在处理后,我们的一些内部软件将更多数据插入到此表中。给定表的碎片至少为 50%。对于最大的表,它是 90%。我们没有 DBA。我知道我们迫切需要一个数据库维护策略。就我的背景而言,我是一名在这家公司兼职的大学生。

我的问题是,聚集索引是解决这个问题的最佳方法吗?是否应该考虑另一个索引?对于这种类型和类似的临时 DBA 任务,是否有任何好的参考资料?

4

4 回答 4

4

索引策略完全取决于您如何查询表以及从各个查询中获得多少性能。

当进行无序插入时(这称为“页面拆分”),聚集索引可以强制对行进行物理重新排序(在磁盘上)。在索引页上没有可用空间的大表中,这可能需要一些时间。

如果您不是绝对需要跨两个字段的聚集索引,那么不要。如果它更像是一种 UNIQUE 约束,那么一定要把它变成一个 UNIQUE 约束。这些不需要重新排序。

确定针对表的典型查询是什么,并相应地放置索引。您拥有的索引越多,数据更改 (INSERTs/UPDATEs/DELETEs) 的速度就越慢。不要创建太多索引,例如在不太可能被过滤/排序的字段上。

通常,仅在一起过滤/排序的字段上创建组合索引。

于 2009-02-15T19:52:05.410 回答
1

仔细查看您的查询 - 那些命中数据表的查询。索引会服务吗?如果您在 (ResultID, FieldName) 上有一个按该顺序排列的索引,但您正在查询给定 Fieldname 的可能 ResultID 值,则 DBMS 很可能会忽略该索引。相比之下,如果您在 (FieldName, ResultID) 上有一个索引,它可能会使用该索引 - 当然对于简单的值查找 ( WHERE FieldName = 'abc')。就唯一性而言,任一索引都运行良好;在查询优化方面,(至少可能)存在巨大差异。

使用EXPLAIN查看 DBMS 如何处理您的查询。

聚集索引与非聚集索引通常是 DBMS 中的二阶优化效果。如果您的索引正确,则聚集索引和非聚集索引之间存在微小差异(聚集索引的更新惩罚更大,作为对稍小的选择时间的补偿)。在担心二阶效应之前,请确保其他所有内容都已优化。

于 2009-02-15T22:02:24.753 回答
0

据我所知,聚集索引还可以。关于其他索引,您需要提供对该表进行操作的典型 SQL 查询。只是突然创建一个索引绝不是一个好主意。您在谈论碎片和索引,这是否意味着您怀疑查询执行速度变慢?或者您只是想缩小/整理数据库/索引?

在非工作时间不时对索引进行碎片整理是个好主意,尽管您必须考虑到频繁/随机插入,在表中留出一些备用空间以防止页面拆分(这确实会影响性能)。

于 2009-02-15T20:02:07.413 回答
0

我知道我们迫切需要一个数据库维护策略。

+1 用于确定需求

就我的背景而言,我是一名在这家公司兼职的大学生

继续学习,获得经验,但同时获得一位经验丰富的顾问。

该表由 24 个工作人员填充,每个工作人员运行 4 个线程

我认为这在工作日是非常关键的任务,而停机是坏消息?如果是这样,请不要附和它。

ResultID 和 Fieldname 上有一个聚集索引

正如您所指出的,ResultID 是 PK 中的第一列吗?

如果是这样,我敢打赌,它的选择性不够,并且根据查询的需求,应该交换 PK 字段的顺序(尽管这个复合键看起来对于集群 PK 来说是一个糟糕的选择)

结果是什么:

从 MyTable 中选择 COUNT(*)、COUNT(DISTINCT ResultID)

例如,如果第一个计数是第二个计数的 4 倍或更多,那么由于 ResultsID 的选择性低,您很可能会优先获得扫描而不是搜索,并且一些简单的更改将带来巨大的性能改进。

此外,Fieldname 非常宽(50 个字符),因此任何二级索引都会在每个索引条目中添加 50 + 4 个字节。这些字段真的是 CHAR 而不是 VARCHAR 吗?

我个人会考虑增加叶页的密度。在 90% 时,您只会留下一些空白 - 可能每页一个。但是对于一个包含 5 亿行的大表,更高的打包密度可能意味着树中的级别更少,因此检索的次数更少。与此相反,对于给定的页面,几乎每个插入都需要页面拆分。这将有利于集群的插入,因此可能不合适(假设您的插入数据可能未集群)。像许多事情一样,您需要进行测试以确定哪种索引键密度最有效。SQL Server 提供了一些工具来帮助分析查询是如何被解析的、它们是否被缓存、它们导致的表扫描次数、哪些查询“运行缓慢”等等。

让顾问进来看看并给你一些建议。这不是一个在这里回答的问题将为您提供一个安全的解决方案来实施。

对于每天有 5 亿行和大量插入的表,您确实需要仔细考虑维护策略。抱歉,但我对进入这种状态的公司感到非常沮丧。

该表需要进行碎片整理(如果您没有聚集索引,您的选项将变得更少,因此请保留它,直到您确定有更好的候选者)。“在线”碎片整理方法将对性能产生适度的影响,并且可能会突然消失 - 如果它们超出时间/CPU限制,可以安全地中止[尽管这很可能需要一些编程]。如果您有一个“安静”插槽,则将其用于表碎片整理和更新索引的统计信息。不要等到周末才尝试一次完成所有桌子 - 在每天的任何安静时间(大概在晚上)尽可能多地做。

对表进行碎片整理可能会导致 Transaction log 使用量大幅增加,因此请确保经常备份任何 TLog(我们有一个 10 分钟的 TLog 备份策略,我们在碎片整理期间将其增加到每分钟一次,以便碎片整理过程不会成为所需 Tlog 空间的定义!)

于 2009-02-15T22:39:34.557 回答