文盲的数据库指令优化心得:第一部分,关于索引

2024-02-25 20:48

本文主要是介绍文盲的数据库指令优化心得:第一部分,关于索引,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先说点废话,用了10年sqlserver了,楞是不知道指令怎么优化,怎么提高效率太失败了,经过2、3个月的重新学习,才明白之前工作中没有出过问题实在太幸运了


本文中出现的大部分心得内容,在网上也能搜索到,对部分内容有误的,也欢迎大家指正


1、先说说索引,反正文盲本身是野路子出身,没系统学过,说的错了大家来指正

首先,索引是用来优化查询效率的,针对于不同的条件,所需要的索引也千奇百怪,如果索引过多,又没有能够有效的覆盖所有需要的字段,还是会降低效率,那么索引到底应该怎么建立呢?

1.1、所有必定出现在条件内的字段建立一个统一索引,然后包含所有输出的字段,这样可以保证执行计划是索引查找(index seek)而不是索引扫描(index scan),同时因为包含了条件和输出内容,所以也不会出现表扫描(table scan)

1.2、所有可能出现的条件单独建立索引并包含主键,然后单独使用该条件进行主键查询,以确保执行计划是索引查找(index seek)

1.3、索引重复字段尽量减少,因为重复字段约多,更新时越慢,更新所表情况越严重

那么有了以上几点,咱们做个实例进行测试

if object_id('test_index') is not null drop table test_index
go
create table test_index(id bigint identity primary key,n1 int,n2 int,n3 int,n4 int,n5 int,n6 int,n7 int,n8 int,n9 int,d1 date,d2 date,d3 date,d4 date,d5 datetime,d6 datetime,b1 bit,b2 bit,b3 bit,b4 bit,s1 varchar(max),s2 varchar(max),s3 nvarchar(max),s4 nvarchar(max))
go
insert into test_index(n1,n2,n3,n4,n5,n6,n7,n8,n9,d1,d2,d3,d4,d5,d6,b1,b2,b3,b4,s1,s2,s3,s4)
values(RAND()*500,RAND()*500,RAND()*500,RAND()*500,RAND()*500,RAND()*500,RAND()*500,RAND()*500,RAND()*500,dateadd(d,-RAND()*500,getdate()),dateadd(d,-RAND()*500,getdate()),dateadd(d,-RAND()*500,getdate()),dateadd(d,-RAND()*500,getdate()),dateadd(d,-RAND()*500,getdate()),dateadd(d,-RAND()*500,getdate()),(case when RAND()*2 > 1 then 1 else 0 end),(case when RAND()*2 > 1 then 1 else 0 end),(case when RAND()*2 > 1 then 1 else 0 end),(case when RAND()*2 > 1 then 1 else 0 end),'','','',''
)
go 2000000

创建一个测试表,扔200万数据进去,来测试一下索引应该怎么玩

第一个指令

select id from test_index where n1>400
来看看执行计划


我们发现,基本上所有的查询都会提示缺少索引,那么我们就来分辨一下索引的条件

假设:n1、n2、d1、b1必定出现在查询条件中,而我们只输出主键,那么我们的索引应该这么建立

CREATE NONCLUSTERED INDEX [n1_n2_d1_b1_inc_id] ON [dbo].[test_index]
([n1] ASC,[n2] ASC,[d1] ASC,[b1] ASC
)
INCLUDE ( 	[id]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

建立好索引后,我们再次运行第一条指令,发现提示的还是缺少索引,那么我们不应该再去建立索引未了适应第一个指令,而是应该将指令变形,以适应我们已有的索引

那么来写第二条指令吧

select id from test_index where n1>40 and n2=n2 and b1=b1 and d1=d1

再看看执行计划如何?


很好,经过我们在指令中加了两句废话,n2=n2,b1=b1,d1=d1这样的条件后,他的执行计划改变了,索引查找(index seek),好吧,sqlserver就是这么个性

那么结论1就是,我们未必需要很多索引,因为我们可以把指令变形,让数据库使用我们所期望的索引,即便实际应用中可能有些条件不完整,我们也要通过废话告诉数据库,来使用已有的索引,也就是1.1中的观点

好了,我们再看看,可能出现的条件,先写个第三条指令

select id from test_index where n1>40 and n2=n2 and b1=b1 and d1=d1 and n5<100


数据库傻掉了,没有使用我们建立的索引,因为n5不在我们的索引范围内,那么我们应该怎么去调整呢,文盲是通过一套组合拳来玩的,首先,建立一个n5为主的,包含主键的索引

CREATE NONCLUSTERED INDEX [n5_inc_id] ON [dbo].[test_index]
([n5] ASC
)
INCLUDE ( 	[id]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

然后把第三条语句变形一下,称为第四条语句

select main.id from test_index main
inner join (select id from test_index where n5<100) app_n5 on main.id=app_n5.id
where n1>40 and n2=n2 and b1=b1 and d1=d1


呵呵,我们的索引又回来了,那么这个语句的变形依据就是1.2的论点了,这样,我们就可以对所有不确定是否参与运算的字段进行单独索引,并且连排序都可以使用这些索引了

例如

select main.id from test_index main
inner join (select id from test_index where n5<100) app_n5 on main.id=app_n5.id
where n1>40 and n2=n2 and b1=b1 and d1=d1
order by n5


select main.id from test_index main
inner join (select id,n5 from test_index where n5<100) app_n5 on main.id=app_n5.id
where n1>40 and n2=n2 and b1=b1 and d1=d1
order by app_n5.n5


对比这两个指令,唯一的区别就是把索引对应的内容单独拿出来排序,而不是在无该字段索引的查询中排序,呵呵,sqlserver还真是个性啊

那么明白了这个内容之后,我们就可以根据执行计划和现有的索引来调整执行格式,而不是无限制的去加索引了

那么,1.3的观点大部分人都已经说明过了,我就简单说一下,如果一个字段出现在多个索引中,那么在更新这个字段的时候,所有相关的索引都会同时更新,有人说过,一个表上的相关索引最好不要超过5个,那么文盲自己的理解则是,同一个字段(除主键外)相关的索引最好控制在三个以下,索引总数到是无所谓



----------------------------------------------------------------------------------------

文盲的数据库指令优化心得:第一部分,关于索引

文盲的数据库指令优化心得:第二部分,指令变形和执行计划


SQL SERVER全面优化-------Expert for SQL Server 诊断系列

l

这篇关于文盲的数据库指令优化心得:第一部分,关于索引的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/746658

相关文章

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

MySQL 强制使用特定索引的操作

《MySQL强制使用特定索引的操作》MySQL可通过FORCEINDEX、USEINDEX等语法强制查询使用特定索引,但优化器可能不采纳,需结合EXPLAIN分析执行计划,避免性能下降,注意版本差异... 目录1. 使用FORCE INDEX语法2. 使用USE INDEX语法3. 使用IGNORE IND

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

虚拟机Centos7安装MySQL数据库实践

《虚拟机Centos7安装MySQL数据库实践》用户分享在虚拟机安装MySQL的全过程及常见问题解决方案,包括处理GPG密钥、修改密码策略、配置远程访问权限及防火墙设置,最终通过关闭防火墙和停止Net... 目录安装mysql数据库下载wget命令下载MySQL安装包安装MySQL安装MySQL服务安装完成

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

MySQL逻辑删除与唯一索引冲突解决方案

《MySQL逻辑删除与唯一索引冲突解决方案》本文探讨MySQL逻辑删除与唯一索引冲突问题,提出四种解决方案:复合索引+时间戳、修改唯一字段、历史表、业务层校验,推荐方案1和方案3,适用于不同场景,感兴... 目录问题背景问题复现解决方案解决方案1.复合唯一索引 + 时间戳删除字段解决方案2:删除后修改唯一字

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

SQL server数据库如何下载和安装

《SQLserver数据库如何下载和安装》本文指导如何下载安装SQLServer2022评估版及SSMS工具,涵盖安装配置、连接字符串设置、C#连接数据库方法和安全注意事项,如混合验证、参数化查... 目录第一步:打开官网下载对应文件第二步:程序安装配置第三部:安装工具SQL Server Manageme

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.