聊聊性能,如何合理设置索引?

简介: 【6月更文挑战第1天】本文介绍了数据库索引过多的索引会使更新表的速度变慢,增大数据库体积和维护成本。索引过多的风险包括降低增删改操作性能、增大数据库体积、增加存储压力和维护开销,以及加大SQL Server优化开销。建议的核心表索引不超过7个,普通表不超过5个,小型表不超过3个。针对索引过多的问题,文章提出需要根据实际需求进行分析并提供解决方案。

1 简介

这里主要介绍索引的功能,索引的作用和原理,它能加速数据查询但过度使用会导致性能下降。索引是一种数据结构,用于快速访问数据库中的信息,通过减少磁盘访问次数提升性能。
以及为什么索引可帮助使用者优化如何查询已经存储的数据的同时,过多的使用反而导致性能下降。

question_ans.png

索引通过最大限度地减少完成查询所需的光盘访问次数来提高数据库性能。

它是一种数据结构技术,用于查找和快速访问数据库中的数据。多个数据库字段用于生成索引。表的主键或候选键在第一列中重复,即搜索键。

为了加快数据检索速度,这些值也按排序顺序保存。应该强调的是,不需要对数据进行排序。

第二列是数据引用或指针,其中包含一组指针,用于保存可以找到该特定键值的磁盘块的地址

索引和优化器提示 可单独使用或一起使用。

索引提示适用于 SELECT,DELETE 和 UPDATE 语句。 索引提示一般在表名之后指定。

2 数据库索引

MySQL和Oracle等数据库本身提供索引的功能,合理创建索引可以提高数据的检索效率,降低数据库服务器IO和CPU的消耗。

但由于索引也会降低更新表的速度,经常增删改的表或字段不适合创建索引,所以在开发初期,我们就应该根据数据库模型表和字段的作用来决定是否为该表建立索引,为数据记录较多的表中,频繁作为查询条件的字段建立索引。

            #python3
        class Article(models.Model):
            "文章"
            title = models.CharField('标题',max_length=200,)
            class Meta:
                indexes = [models.Index(fields=['title']),]

3 索引过多的问题

表所允许的索引数量,数据库允许的索引数量,最大并发事务处理能力,负载均衡能力,最大连接数。

  • 索引太多的问题

    对于太小的表,经常更新的的属性和表,属性值很少的查询,过长的属性,特殊数据类型的属性比如大文本,多媒体数据,不出现或很少出现的属性不宜建立索引。

而对于常用属性建立太多属性将会降低增删改查的性能。

也会导致数据库体积变大,加大数据库优化的开销,数据库将对索引定义建立列计算统计信息更新开销,过多的索引导致更新范围大,时间变长。索引失效维护成本高。

  • 索引过多

是指单表上非聚集索引数量太多,至于多少才为太多,这个实际上没有标准,虽然某些书上有说过单表上不要超过6个索引,但是那些书是 通常是很久远的书籍(大概10年前左右),那时候的硬件资源还没比较紧张,不可能支持太多索引。

但是即使是今天的硬件资源,随着系统的复杂程度和数据量的 增长,硬件资源也容易不足,同时索引过多也会带来很多风险。 以下详细解读。

4 索引过多具体风险主要有以下几个:

  • 降低增删改操作的性能。

由于增删改操作特别是删、增两个,往往引发聚集索引键的变更,标上的非聚集索引叶节点存储了聚集索引键,所以也会连带被更 新。而这些非聚集索引往往是没有提高这些操作的性能,反而对操作带来负面影响。这就是所谓的牵一发而动全身。

如果有些增删改操作带有WHERE条 件,这些情况下,有些索引能提高性能,比如百万级别的表中删除一行数据,如果没有索引(假设连聚集索引也没有),那么就只有扫描全表删除,那速度简直无法接受。

  • 过多索引还导致了数据库“体积”变大。

本质上,数据库的性能问题几乎都是由于“体积”过大导致的。我们知道,聚集索引就是表本身,表多大,聚集索 引几乎就有多大,根据B-Tree的层级,可能会比表更大(不过一般大不了多少)。而非聚集索引叶子节点由于存储了索引键的数据,索引也有一定体量。

  • 过多索引导致存储压力和维护开销。

由于SQL Server不直接访问磁盘,每个操作都需要先把数据从磁盘加载到内存中,内存的容量相对磁盘来说又比较小,一旦索引很大,查询过程造成的内存压力也会随 之而来,对数据缓存和计划缓存都有不可忽视的影响。对聚集索引的维护,比如重建,会引发非聚集索引的连带效应。索引越多速度越慢。很多系统并没有充足的时 间让你任意维护索引。

  • 加大了SQL Server优化开销。

虽然通常优化引擎不会花太多时间在优化上,最起码相对于执行而言,优化的时间你可能感知不到,但是过度优化、编译重编译,都会对 CPU带来压力。

当索引很多时,优化器必须针对查询及上面的统计信息进行分析,如果有一些索引都能支持这个查询时,优化器又必须比对哪个索引开销更低。 要优化器选择也有选择恐惧症,太多的选择它就会折中,不一定会花更多资源去选择最优方案,万一当时其他操作的影响导致优化器选择了不合理的索引,性 能反而更差。

统计信息更新开销,默认情况下,SQL Server会对索引定义中的列计算统计信息,这种统计信息是索引级别的,每个索引有自己的统计信息,索引越多,由于数据变更或者其他变更带来统计信息更新时,需要更新的范围就越大,时间越久。

  • 索引失效:
    在运维的数据库时,不定期可能出现某些功能卡顿的情况,通过重建索引,功能恢复一定时间的稳定,但是过一段时间 后又出现了卡顿。

从表象看来,这类似与索引失效的情况,但是目前官方资料中并没有出现索引失效的描述,所以可以认为索引失效其实只是个表象,更多的是优化器对 索引选择的混乱。

通过降低索引的数量和提高每个索引的重用度,这种情况目前再无发生。简单来说,对于OLTP数据库,单表索引不应该过多。

5 总结

一个简单的经验标准:

对于核心表:所有索引不要超过7个。
对于普通表:所有索引不要超过5个。
对于小型表:所有索引不要超过3个。

当单表有很多索引(比如上面提到的20多个)时,就应该考虑是否真有必要维持这种数量,在本系列的最后部分会给出解决方案。

当然极端情况下,20多个索引的表性能表现也不一定不好。当然,总是需要按照实际场景需求去分析的。

目录
相关文章
|
边缘计算 数据可视化 物联网
node-red介绍
Node-RED最初是IBM在2013年末开发的一个开源项目——基于数据流(dataflow)的可视化编程工具。
node-red介绍
|
2月前
|
安全 Linux iOS开发
Cisco Secure Client (AnyConnect) 5.1.17.3382 发布下载
Cisco Secure Client (AnyConnect) 5.1.17.3382 (macOS, Linux, Windows & iOS, Android) - 远程访问客户端
1392 1
Cisco Secure Client (AnyConnect) 5.1.17.3382 发布下载
|
10月前
|
人工智能 自然语言处理 文字识别
RAG效果不佳?先别急着微调模型,这几个关键节点才是优化重点
本文深入探讨了RAG(Retrieval Augmented Generation)技术的实现细节与优化策略,指出在AI应用开发中,RAG常被视为黑盒导致问题定位困难。文章从文档分块(Chunking)、索引增强(语义增强与反向HyDE)、编码(Embedding)、混合检索(Hybrid Search)到重排序(Re-Ranking)等关键环节进行了详细解析,强调需结合具体场景对各模块进行调优,以提升召回率与精确率的平衡,并倡导从快速使用走向深度优化的实践路径。
1367 33
RAG效果不佳?先别急着微调模型,这几个关键节点才是优化重点
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
5212 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
7月前
|
缓存 NoSQL Redis
千万级数据表的count(*)查询优化
针对千万级数据表`user_factor_auth_record`的COUNT查询性能问题,可通过“避免实时计数、独立计数表、Redis缓存”三大方案优化。优先从业务层面取消总条数展示,减轻数据库压力;若需精确值,可借助事务维护独立计数表,或定时缓存至Redis,分摊开销、提升查询效率。
541 5
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 > Java系统属性 > application.properties > application.yml > application.yaml。
1357 0
|
监控 数据库 索引
如何优化数据库索引?
【8月更文挑战第23天】如何优化数据库索引?
434 4
|
Java Spring
ApplicationContextAware 的理解和应用
ApplicationContextAware 的理解和应用
401 2
|
存储 Java 关系型数据库
定时任务配置技巧:将表达式配置在业务员代码之外的方法
该文档介绍了三种不同的方法来定义和管理Java中的定时任务。首先,通过在数据库中创建一个表来存储定时任务的执行周期,并在Spring Boot应用中使用`@Scheduled`注解配合数据库查询来动态执行定时任务。其次,将定时任务的配置移动到Apollo配置中心,利用Apollo的配置能力来控制定时任务的执行。最后,使用Quartz框架并结合Apollo配置文件,动态地管理定时任务的触发间隔和执行时间。此外,还提到了在多机器环境中,可以使用分布式锁来避免任务重复,并推荐了xxl-JOB和elastic-job作为更专业的定时任务解决方案。
429 2