百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

挽救数据库性能的30条黄金法则

bigegpt 2024-08-04 11:39 4 浏览

1. 优化查询,应尽量避免全表扫描,应该在用于检索数据和排序数据的字段上建立索引,如where子句用于搜索,order by子句用于排序,所以在这两个子句涉及到的字段上需要建立索引。

2. 应该避免在where子句中使用否定的操作符,如不等于(!=或<>)、否则数据库引擎将放弃使用索引而进行全表扫描。

3. 在尽量避免在where子句中使用或(or)作为连接条件,否则数据库引擎将放弃使用索引而进行全表扫描。如下面的SQL语句可能会带来性能问题

select id,name,age from persons 
where name = 'Bill' or age > 30

由于这条SQL语句使用了or,所以数据库引擎会进行全表扫描,为了避免全表扫描,可以将这条SQL语句改成下面的形式。

select id,name,age from persons where name = 'Bill'
union all
select id,name,age from persons where num = 20

4. 应该尽量避免在where子句中使用null进行判断,否则数据库引擎将放弃使用索引而进行全表扫描。先看下面的SQL语句:

select id,name,age from persons where age is null

为了避免使用null,可以设置age字段的默认值为0,这样就可以通过下面的SQL语句达到同样的结果。

select id,name,age from persons where age = 0

5. 尽量不用使用like检索数据,因为也会导致数据库引擎将放弃使用索引而进行全表扫描。

例如,下面的SQL语句执行的效率会非常低:

select id,name,age from persons where name like '%John%'

如果真想进行模糊查询,可以使用全文检索。

6. 在where子句中应尽量避免在字段中使用表达式(包括函数运算、算数运算等),否则据库引擎将放弃使用索引而进行全表扫描。例如,下面的SQL语句执行的性能比较差

select id,name,age from persons age / 2 > 12

应该利用表达式变换,改成下面的形式:

select id,name,age from persons age > 2 * 12

或者干脆改成下面的形式:

select id,name,age from persons age > 24

7. 应尽量避免使用in和not in,否则也会导致全表扫描。

如并不推荐下面的写法:

select id, name,age from persons where age in (22,23,24)

如果数值是连续的,应该使用between,而不要用in,如果数值是不连续的,可以分成多个SQL,用union all连接查询结果。

select id,name,age from persons where age between 22 and 24

select id,name,age from persons where age = 22
union all
select id,name,age from persons where age = 26
union all
select id,name,age from persons where age = 30

8. 应该尽量避免在where子句中使用参数,否则也将导致全表扫描。这是因为参数需要在SQL运行时才进行替换,而SQL优化(使用索引属于优化的一部分)是在编译时进行的。所以数据库引擎在检索到参数时,由于参数的具体指是未知的,所以也就无法优化了,当然也就无法使用索引了。

不使用索引的SQL语句:

select id,name,age from persons where name = @name

为了使用索引,可以改成下面强制使用索引的方式:

select id,name,age from persons with(index(name_index)) where name = @name

其中name_index是建立在name字段上的索引名。

9. 尽量不要执行一些没意义的查询,如条件完全为false的查询:

select id,name,age into persons1 from persons where age < 0

这样的代码会返回一个空结果集,而且会大量消耗系统资源,如果真的想建一个空表,应该直接用create table语句。

10. 如果使用的索引是符合索引,只有使用该符合索引的第1个字段作为条件时才能保证数据库引擎使用该符合索引,否则该符合索引不会被使用。并且应该尽可能让字段顺序与索引顺序一致。例如,name_index是first_name和last_name字段的符合索引,使用下面的SQL语句会使用该索引。

select id,first_name,last_name
from persons
where first_name = 'Bill'

11. 如果非要在SQL语句中使用in,那么使用exists代替in是一个好主意:

select id,num from t 
where num in (select num from h)

应该用下面的SQL语句代替:

select id,num form t
where exists(select 0 from h where num = t.num)

12. 索引并不是在任何时候都有效,如果索引列有大量重复的数据,那么数据库引擎可能不会去利用索引。例如,sex字段的值只有两种可能:male和female,可能这两个值各占一半,这样在sex字段上建立索引就没有任何意义。

13. 能使用数值型字段就使用数值型字段。因为比较数值型字段的效率要远比字符型字段的效率高,这是因为比较字符型的值,要一个字母一个字母地比较,而数值型的值,只是比较一个数。所以如果只包含数值信息的值,应该尽量使用数值类型的字段。例如,age、salary等。

14. 应尽量避免使用固定长度的字段,如char、nchar。使用可变长度的字段是一个非常好的选择。因为可变长度字段占用的空间是按需分配的,所以占用空间比较少。对于查询来说,毫无疑问,当然是占用空间小的字段的查询效率更高了。

15. 尽量按需返回字段和记录,例如:

select id,name,age from persons where age > 20

尽量避免使用“*”返回所有不需要的字段,也不需要一下就查询出所有的记录,如下面的SQL语句在数据量很大时查询效率是非常低的。

select * from persons

16. 索引有利有弊,增加索引,可以提高select的执行效率,但付出的代价是在进行insert和update操作时,可能会降低效率。因为进行insert和update操作时通常需要重建索引。所以在一个表中并不是索引越多越好。我的建议如下:(1)如果一个表大多数时进行的是select操作,那么索引多一些大多数时候确实可以提升性能,但这有一个前提,就是不能频繁进行insert和update操作。(2)一个表中的索引数不能太多,最好不要超过6个,否则就好考虑优化一下数据库了。

17. 应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

18. 应尽量避免向客户端返回大理数据,如果数据量过大,应该改变一下需求,或采用分页返回的方式,如使用MySQL中的limit子句现在返回的数据。

19. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该采用其他方案。

20. 使用基于游标的方法或临时表方法之前,应先寻找基于数据集的解决方案来解决问题,基于数据集的方法通常更有效。

21. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先用 truncate table清除表中的数据 ,然后 用drop table彻底删除物理表 ,这样可以避免系统表的较长时间锁定。

22. 避免频繁创建和删除临时表,以减少系统表资源的消耗。

23. 在新建临时表时,如果一次性插入的数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高执行效率;如果数据量不大,为了缓和系统表的资源,应先create table,然后使用insert插入数据。

24. 在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

25. 尽量避免大事务操作,提高系统并发能力。

26. 应尽量一次性插入多条数据,例如,使用下面的SQL语句性能会很低:

insert into persons(id,name,age) values('Bill',24)
insert into persons(id,name,age) values('Mike',26)
insert into persons(id,name,age) values('John',20)

为了提升性能,可以一次性插入这3条记录。

insert into persons(id,name,age) values('Bill',24),('Mike',26),('John',20)

27. 如果不得不使用like进行模糊查询时,不要在关键字前面加%。

反例:

select id,name,age from persons where name like '%abc%'

如果在关键字前面加%,那么查询是肯定要走全表查询的。

正例:

select id,name,age from persons where name like 'abc%'

28. 尽量用union all代替union

union和union all的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的cpu运算,加大资源消耗及延迟。所以当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用union all而不是union。

29.尽量使用等值连接

等值连接就是inner join,也称为内联进,而left join和right join是外连接。

先看下面的SQL语句

select a.id,a.name,b.id,b.name from a left join b on a.id = b.id

select a.id,a.name,b.id,b.name from a right join b on a.id = b.id

select a.id,a.name,b.id,b.name from a inner join b on a.id = b.id

上面的3条SQL语句,前两条分别使用了左连接和右连接,而最后一条使用了内连接,经过实际运行,使用内连接的SQL语句的执行效率明显优于左连接和右连接。所以在能满足需求的前提下,应该尽可能使用内连接(等值连接)。

30. 尽量用外连接来替换子查询反例

select id,name from a where exists (select id from b where id>=10 and a.product_id=b.product_id)

在上面的SQL语句中,数据库引擎会先对外表a执行全表查询,然后根据product_id逐个执行子查询,如果外层表(a表)中的数据非常多,查询性能会非常糟糕。所以应该将SQL语句改成下面的形式:

select id,name from a inner join b on A.product_id=b.product_id where b.id>=10

相关推荐

科氪 | 华硕天选6系列正式发布,搭载满功耗RTX 5060实际到手5999元起

5月19日晚,华硕旗下潮玩新次元游戏本天选6系列正式发布。作为Z世代青年的潮酷游戏装备,天选6系列再一次印证了其出色的综合实力。搭载满功耗RTX5060笔记本电脑GPU的天选6Pro以及天选6皆...

最新历史最低价显卡汇总!低端高端一网打尽

文|宋金戈责编|吕东兴总编|唐迪近期开展的618大促,各个品类尤其是数码科技好物的产品优惠都诚意满满,而作为消费者最关心的大类之一,显卡在最近同样表现不俗——华硕、技嘉等多个品牌,从1660s...

DNF:南山必胜客“败诉”,TX被DD373实锤,谁说玩家只有使用权?

TX和DD373的官司终于落下帷幕,南山必胜客终于中断了传奇。TX这一次被判定败诉。其中关于游戏账号和虚拟财产的问题,最受玩家关注。之前TX所说的:游戏账号不是玩家私有财产,游戏币更不是,只有使用权!...

Switch最新SX OS破解系统发布:可运行国行卡带xci镜像了

本周,TX团队(Team-Xecuter)发布了SXOS自制系统的最新版本,v2.9.5Beta,该版本支持了任天堂最新的V10.0.0和v10.0.1固件,同时改善了兼容性,优化了本地联机的稳定...

神舟战神TX8R5 QHD游戏本电脑今晚开售:2.5K屏+RTX4060,6999元

IT之家4月9日消息,神舟战神TX8R5QHD游戏本电脑今晚12点正式开售,仅有16GB+512GB一个版本可选,售价6999元。神舟战神TX8R5QHD搭载13代酷...

开创第三代手游商业模式《武极天下》推无商城玩法

翻阅游戏论坛与贴吧,大家对网络游戏的一些“坑爹”的设定抱怨不已,不是游戏职业设定不合理,就是游戏太烧钱,在游戏中被碾压的抬不起头,最后从玩游戏变成了被游戏玩,俨然游戏本质完全变味。由巨人移动自主研发并...

真满血Gen5电竞存储神装!佰维X570 Pro天启高速固态硬盘测评

2025一开年,对于存储行业来说,就是速度狂飙的开局。各固态硬盘品牌PCIe5.0SSD纷纷亮相,开启了新一轮的性能PK。在2024年异常活跃的佰维科技,也于CES期间推出了佰维X570PRO...

Kingston FURY Renegade G5评测 最速PCIe5.0固态硬盘诞生

【ZOL中关村在线原创评测】说起KingstonFURYRenegade叛逆者的大名,相信PCDIY玩家都知道这是金士顿高端存储的代名词,尤其是内存产品给人印象尤为深刻。实际上它还有固态硬盘系列...

《武极天下》力挺苹果TestFlight创业界先河

关于革旧鼎新,有人说就像是摸石头过河,在摸索中前行。一场正真的创新改革会带来什么?在数字行业,苹果公司的每一个产品都代表着一个时代的开启,它独立的操作系统、顺应用户需求的体验设计,在十几年时间内收获了...

闪迪至尊超极速移动固态硬盘USB4版评测 超越SSD的三防猛兽

移动固态硬盘,凭借TB级的容量和远超传统移动机械硬盘几倍、十几倍的速度,当仁不让地成为高效移动存储的代名词,为4K/8K超高清内容创作、海量文件备份带来了超乎想象的效率提升。国际知名品牌SanDisk...

RTX5070笔记本有哪些:游戏笔记本电脑哪个牌子好?

RTX5070游戏本,个人其实不是很喜欢,对于新款显卡,要不就考虑RTX5060,要不就考虑12GB显存的RTX5070Ti这样好一些,从RTX5070显卡的游戏本的量,也能看出来,估计5060会更多...

破军天下安装指南详解 游戏安装方法介绍

破军天下游戏怎么正确安装?破军天下安装方法是什么?对于破军天下中的安装问题,今天安趣网小编就为各位玩家小伙伴来好好的讲解下,让我们一起来看看,破军天下怎么正确安装游戏的吧!希望大家喜欢!安卓系统(An...

从高性能轻薄本到硬核电竞本 华硕天选新品解锁全场景体验

来源:环球网【环球网科技综合报道】5月19日,华硕天选多款笔记本新品正式发布。其中,14英寸轻薄全能本标杆华硕天选Air2025正式发布,显卡升级至GeForceRTX5060笔记本电脑GPU...

笔记本无线网卡有哪几种 有必要对其升级吗?

无线网卡是很多朋友购买笔记本时容易忽视的部分,相比较处理器、内存、显卡和硬盘,无线网卡几乎不可选,而且很少有厂商提到自家产品采用的无线网卡型号。大家可能遇到过这种情况:为什么手机可以连接到5Ghz,而...

下班了才发现,你的手机里藏着5个定时炸弹!

各位打工人累了一天终于可以躺平刷手机了吧?且慢!工信部最新通知,有些App比加班还可怕!它们可能正在偷偷收集你的信息,比你的老板还要了解你!今天就让我们一起来扒一扒这些“职场内鬼“,看看你的手机里有没...