在我曾经工作过的前公司,经验法则是一个表应该只有一个索引(允许奇怪的异常,并且某些父表几乎所有其他表都被引用,因此非常频繁地更新)。
通常情况下,索引的成本与获得的成本相同或更高。请注意,此问题与indexed-view-vs-indexes-on-table不同,因为动机不仅仅是报告。
这是真的吗?这种指数纯粹主义值得吗?
在你的职业生涯中,你通常会避免使用索引吗?
关于指数的一般大规模建议是什么?
目前,在最后一家公司,我们使用SQL Server,因此也欢迎任何特定于产品的指南。
答案 0 :(得分:35)
您需要创建与创建所需数量完全相同的索引。不多也不少。就这么简单。
每个人都“知道”索引会减慢表上的DML语句。但由于某些原因,很少有人真的费心去测试它在上下文中的“慢”程度。有时我会觉得人们认为添加另一个索引会为每个插入的行添加几秒钟,这使得它成为一个改变业务权衡的游戏,一些虚构的热门用户应该在董事会会议室决定。
我想分享一个我刚刚在我2岁的电脑上使用标准MySQL安装创建的示例。我知道您标记了SQL Server的问题,但该示例应该很容易转换。我将 1,000,000 行插入三个表中。一个表没有索引,一个表包含一个索引,一个表包含九个索引。
drop table numbers;
drop table one_million_rows;
drop table one_million_one_index;
drop table one_million_nine_index;
/*
|| Create a dummy table to assist in generating rows
*/
create table numbers(n int);
insert into numbers(n) values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
/*
|| Create a table consisting of 1,000,000 consecutive integers
*/
create table one_million_rows as
select d1.n + (d2.n * 10)
+ (d3.n * 100)
+ (d4.n * 1000)
+ (d5.n * 10000)
+ (d6.n * 100000) as n
from numbers d1
,numbers d2
,numbers d3
,numbers d4
,numbers d5
,numbers d6;
/*
|| Create an empty table with 9 integer columns.
|| One column will be indexed
*/
create table one_million_one_index(
c1 int, c2 int, c3 int
,c4 int, c5 int, c6 int
,c7 int, c8 int, c9 int
,index(c1)
);
/*
|| Create an empty table with 9 integer columns.
|| All nine columns will be indexed
*/
create table one_million_nine_index(
c1 int, c2 int, c3 int
,c4 int, c5 int, c6 int
,c7 int, c8 int, c9 int
,index(c1), index(c2), index(c3)
,index(c4), index(c5), index(c6)
,index(c7), index(c8), index(c9)
);
/*
|| Insert 1,000,000 rows in the table with one index
*/
insert into one_million_one_index(c1,c2,c3,c4,c5,c6,c7,c8,c9)
select n, n, n, n, n, n, n, n, n
from one_million_rows;
/*
|| Insert 1,000,000 rows in the table with nine indexes
*/
insert into one_million_nine_index(c1,c2,c3,c4,c5,c6,c7,c8,c9)
select n, n, n, n, n, n, n, n, n
from one_million_rows;
我的时间是:
我的SQL比统计和数学更好,但我想是这样的: 在我的表中添加8个索引,总共添加了(6,98-1,5)5,48秒。然后,每个索引将为所有1,000,000行贡献0,685秒(5,48 / 8)。这意味着每个索引每行增加的开销将为0,000000685秒。 有些人会召集董事会成员!
总之,我想说上述测试用例并不是一个糟糕的事。它只是表明,今晚,我能够在单个用户环境中将1,000,000个连续整数插入表中。您的结果将不同。
答案 1 :(得分:8)
这太荒谬了。首先,您需要多个索引才能正确执行。例如,如果您有主键,则会自动拥有索引。这意味着你不能使用你描述的规则索引任何其他内容。因此,如果您不索引外键,连接将会很慢,如果您没有索引where子句中使用的字段,查询仍然会很慢。是的,你可以有太多的索引,因为它们需要额外的时间来插入和更新和删除记录,但只有一个并不危险,要求系统运行良好。我发现用户可以容忍更长的插入时间,而不是容忍更长的查询时间。
现在异常可能是一个系统每秒从一些自动化设备中读取数千个读数。这是一个通常没有索引来加速插入的数据库。但通常这些类型的数据库也不用于读取,而是每天将数据传输到索引的报告数据库。
答案 2 :(得分:6)
是的,当然 - 表上的索引太多可能比没有索引更糟糕。但是,我认为“每桌最多一个索引”规则没有任何好处。
对于SQL Server,我的规则是:
找到正确的指数组合 - 权衡加速查询的优点与INSERT,UPDATE,DELETE的额外开销 - 不是一个精确的科学 - 它更多的是关于技术诀窍,经验,测量,测量,并再次测量。
任何固定的规则都必然会比其他任何事情更具反作用.....
关于索引的最佳内容来自Kimberly Tripp - 索引女王 - 见她blog posts here。
答案 3 :(得分:2)
除非你喜欢非常慢的读取,否则你应该有索引。不要过火,但也不要害怕对他们持开放态度。每个FK都应该编入索引。您将在插入其他表时查找每个列,以确保设置引用。该指数有所帮助。以及索引列经常用于连接和选择的事实。
我们有一些很少插入的表,有数百万条记录。其中一些表格也很宽泛。这些表有15个以上的索引并不罕见。其他具有大量插入和低读取的表我们可能只有少数索引 - 但每个表的一个索引是疯狂的。
答案 4 :(得分:1)
每个插入更新索引一次(每个索引)。速度增益适用于每个选择。因此,如果您不经常更新并经常阅读,那么额外的工作可能是值得的。
如果您执行不同的选择(意味着您筛选的列不同),则为每种类型的查询维护索引非常有用。如果您经常查询的列数有限,则可以使用。
但通常的建议是:如果你想知道哪个是最快的:个人资料!
答案 5 :(得分:1)
在很大程度上取决于您的架构和您通常运行的查询。例如:如果您通常需要选择表的60%以上的行,索引将无法帮助您,表扫描比索引扫描然后查找行更便宜。在表的不同部分中选择少量行或在查询中用于连接的聚焦查询可能会从索引中受益。正确位置的正确索引可以决定功能。
索引占用空间,因此在表格上制作太多索引可能会产生相反的效果,原因与上面列出的相同。扫描5个索引然后执行行查找可能比简单的表扫描要贵得多。
好的设计是关于知道何时归一化以及何时不归属的综合。 如果您经常加入特定列,请使用索引检查IO计划,不要。作为一般规则,我避免使用超过20列的表。这通常表明数据应该规范化。在表上有超过5个索引,并且您可能使用的索引空间比主表更多,请确保这是值得的。这些规则只是最轻量级的指导,而且取决于数据在查询中的使用方式以及数据更新配置文件的外观。
试验您的查询计划,了解您的解决方案如何通过索引改进或降级。
答案 6 :(得分:1)
当然,您应该注意不要为每个表创建太多索引,但每个表只使用一个索引并不是一个有用的级别。
要使用的索引数取决于表的使用方式。经常更新的表通常具有的索引少于比更新时更频繁读取的索引。
我们有一些表每两分钟由一个作业定期更新,但它们经常被不同的查询读取,因此它们有多个索引。例如,一个表有24个索引。
答案 7 :(得分:0)
每个表必须有一个PK,当然它是索引的(通常是一个聚簇的),然后每个FK也应该被索引。
最后,您可能希望索引经常排序的字段,如果它们的数据差异很大:对于在具有100万条记录的表中只有5个可能值的字段,索引将不是一个很大的好处
我倾向于使用索引进行简约化处理,直到数据库开始填充,然后......慢一些。很容易识别瓶颈并在那时添加正确的索引。
答案 8 :(得分:0)
必须仔细设计使用索引优化检索以反映实际的查询模式。当然,对于具有主键的表,您将至少有一个聚簇索引(这就是数据的实际存储方式),然后任何其他索引都会利用数据的布局(聚簇索引)。
在分析针对表执行的查询之后,您需要设计一个覆盖它们的索引。这可能意味着构建一个或多个索引,但这在很大程度上取决于查询本身。只能通过查看列统计数据才能做出这个决定
对于主要插入的表,即ETL表或其他东西,则不应创建主键,或者实际删除索引并在数据更改太快或完全删除/重新创建时重新创建它们。
我个人会害怕进入一个具有每表比率的硬编码索引规则的环境。