怎么提高数据库查询效率

怎么提高数据库查询效率,第1张

提高查询效率首先要想到的就是加索引,那什么是索引呢?

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

如何使用索引呢?

首先索引有窄索引和宽索引两个概念,窄索引是指索引的列数为1~2,宽索引就是说索引的列数大于2。

因为窄索引的效率要高于宽索引,所以能用窄索引就不要使用宽索引。

那么对单字段索引和复合索引应该如何使用?

目录

单字段索引的情况:

复合索引的优势:

两者的比较:

单字段索引的情况:

1.表的主键,外键必须有索引

2.数据量超过300的表应该有索引

3.经常与其他表进行连接的表,在连接字段上应该建立索引

4.经常出现在where字句中的字段,特点是大表的字段,应该建立索引

5.索引应该建在选择性高的字段上

6.索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建立索引

7.尽量用单字段索引代替复合索引,复合索引的建立需要仔细的斟酌

复合索引的优势:

1.单字段索引很少甚至没有

2.复合索引的几个字段经常同时以AND的方式出现在where语句

当where语句中的条件是OR时,索引不起作用。

两者的比较:

以一个sql语句来举例:SELECT * FROM STUDENT WHERE SEX="男" AND SAGE=18

若在sex 和 sage 两个字段分别创建了单字段索引,mysql查询每次只能使用一个索引,虽然对于未添加索引时使用全盘扫描,我们的效率提升了很多,但如果在sex 和 sage两个字段添加复合索引,效率会跟高,如: 创建(sex, age,teacher)的复合索引,那么其实相当于创建了(area,age,teacher)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。

那对于两者优缺点的比较:

1.对于具有2个用and连接条件的语句,且2个列之间的关联度较低的情况下,复合索引有一定优势。

2.对于具有2个用and连接条件的语句,且2个列之间的关联度较高的情况下,复合索引有很大优势。

3.对于具有2个用or连接条件的语句,单索引有一定优势,因为这种情况下复合索引将会导致全表扫描,而前者可以用到indexmerge的优化。

以上就是如何提高查询效率的全部内容,如果有帮助到你的话记得点个关注哟

尽量不要使用 or 使用or会引起全表扫描 将大大降低查询效率

alice like % &abigale&% 会使索引不起作用(针对sqlserver)

经过实践验证 charindex()并不比前面加%的like更能提高查询效率 并且charindex()会使索引失去作用(指sqlserver数据库)

字段提取要按照 需多少 提多少 的原则 避免 select * 尽量使用 select 字段 字段 字段 实践证明 每少提取一个字段 数据的提取速度就会有相应的提升 提升的速度还要看您舍弃的字段的大小来判断

order by按聚集索引列排序效率最高 一个sqlserver数据表只能建立一个聚集索引 一般默认为ID 也可以改为其它的字段

能使用exists和not exists尽量使用 避免使用in或not in

能使用表连接尽量使用 避免使用exists和not exists

SET NOCOUNT ON

正确使用UNION和UNION ALL

慎用SELECT DISTINCT

少用游标

使用表的别名(Alias)

当在SQL语句中连接多个表时 请使用表的别名并把别名前缀于每个Column上 这样可以减少解析的时间并减少那些由Column歧义引起的语法错误

尽量少使用游标

原因很简单就是游标的算法是最原始的计算机算法(和for if等语句一样 一条条搜索来算效率极低)

而sql语句用的是集合运算速度则快的多如果用索引速度则很快(用了指针)

创建索引

a 聚集索引:

聚集索引是磁盘存储和逻辑显示是一样的

mssql表的主键一般是聚集索引主键(每一条记录唯一确定)

创建的主键自动会是聚集索引

如有一个非常大的表(有百万行)很长时间磁盘存储上会有类似碎片(磁盘填充率效率低一般是频繁删除造成的)

要提高它的性能的最简洁办法是:把这个表的主键去掉再保存后然后重新设主键再保存

(这个表就会在磁盘上重新整理排序性能当然会提高哟)

b 非聚集索引:

非聚集索引是在外面建立小的附加表(一种树形结构大多数是B或B+树)

读(遍历select等sql语句)表特快但写(updatedelete insert等sql语句)表性能会略微下降

针对数据量大的表建议非聚集索引不要超过 个(节省额外磁盘负担)

不要给类似 性别 列创建索引

死锁:

是指有线程在读一条记录别的线程读这条记录就要等待

在mssql中只要长期占那条记录的线程去掉死锁就会解除

在mssql中锁是针对每一行记录(所以性能不错)

经常产生锁的原因有:

a 在sql语句中使用事务语句(特别是事务中当查询比较耗时)

b 在前台的应用程序的connetion冲突(未关闭)

c 多表联合查询(尤其是在打开大的数据集时)

sql语句优化

a is null not or in 不会用索引

b 避免在索引列上使用计算或函数处理(索引会大失性能) 还有 % 有的甚至会全失索引性能

c SELECT中避免使用 * (宁可把需要字段列出来而不要用*去把所有的字段都列出来)

d 避免相关子查询(select中套select)

e where的条件中 =>exists>in (指性能)

f order by group by having distinct 等语句要慎用(因为它们效率不高它们是先把数据到临时表中再进行处理的)

g 聚集索引如有 个字段组成(tt 和tt )tt 在前面where的条件中如只用tt 字段来判断就会用到一半的聚集索引

where的条件中如tt 和tt 字段都用来判断了就会全用到聚集索引

where的条件中如只用tt 字段来判断就会用不到聚集索引了

尽量不要使用TEXT数据类型

除非你使用TEXT处理一个很大的数据 否则不要使用它 因为它不易于查询 速度慢 用的不好还会浪费大量的空间

一般的 VARCHAR可以更好的处理你的数据

尽量不要使用临时表

尽量不要使用临时表 除非你必须这样做 一般使用子查询可以代替临时表 使用临时表会带来系统开销

如果前台的代码你是使用数据库连接池而临时表却自始至终都存在 SQL Server提供了一些替代方案 比如Table数据类型

尽量少使用外键和触发器

因为在mssql中这些功能的性能做得不是很好随便动一下表(它就会到相关的表去搞判断有很多情况并不需要)在后台消耗资源大

lishixinzhi/Article/program/Oracle/201311/16744

数据千万级别之多,占用的存储空间也比较大,可想而知它不会存储在一块连续的物理空间上,而是链式存储在多个碎片的物理空间上。可能对于长字符串的比较,就用更多的时间查找与比较,这就导致用更多的时间。

可以做表拆分,减少单表字段数量,优化表结构。

在保证主键有效的情况下,检查主键索引的字段顺序,使得查询语句中条件的字段顺序和主键索引的字段顺序保持一致。

主要两种拆分 垂直拆分,水平拆分。

垂直分表

也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。 一般是针对 那种 几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。

垂直分库针对的是一个系统中的不同业务进行拆分,比如用户User一个库,商品Product一个库,订单Order一个库。 切分后,要放在多个服务器上,而不是一个服务器上。为什么? 我们想象一下,一个购物网站对外提供服务,会有用户,商品,订单等的CRUD。没拆分之前, 全部都是落到单一的库上的,这会让数据库的单库处理能力成为瓶颈。按垂直分库后,如果还是放在一个数据库服务器上, 随着用户量增大,这会让单个数据库的处理能力成为瓶颈,还有单个服务器的磁盘空间,内存,tps等非常吃紧。 所以我们要拆分到多个服务器上,这样上面的问题都解决了,以后也不会面对单机资源问题。

数据库业务层面的拆分,和服务的“治理”,“降级”机制类似,也能对不同业务的数据分别的进行管理,维护,监控,扩展等。 数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。 数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。

水平分表

针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库 *** 作还是有IO瓶颈。不建议采用。

水平分库分表

将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

水平分库分表切分规则

1. RANGE

从0到10000一个表,10001到20000一个表;

2. HASH取模

一个商场系统,一般都是将用户,订单作为主表,然后将和它们相关的作为附表,这样不会造成跨库事务之类的问题。 取用户id,然后hash取模,分配到不同的数据库上。

3. 地理区域

比如按照华东,华南,华北这样来区分业务,七牛云应该就是如此。

4. 时间

按照时间切分,就是将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据 被查询的概率变小,所以没必要和“热数据”放在一起,这个也是“冷热数据分离”。

分库分表后面临的问题

事务支持

分库分表后,就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价; 如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。

跨库join

只要是进行切分,跨节点Join的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求得到关联数据。

跨节点的count,order by,group by以及聚合函数问题

这些是一类问题,因为它们都需要基于全部数据集合进行计算。多数的代理都不会自动处理合并工作。解决方案:与解决跨节点join问题的类似,分别在各个节点上得到结果后在应用程序端进行合并。和join不同的是每个结点的查询可以并行执行,因此很多时候它的速度要比单一大表快很多。但如果结果集很大,对应用程序内存的消耗是一个问题。

数据迁移,容量规划,扩容等问题

来自淘宝综合业务平台团队,它利用对2的倍数取余具有向前兼容的特性(如对4取余得1的数对2取余也是1)来分配数据,避免了行级别的数据迁移,但是依然需要进行表级别的迁移,同时对扩容规模和分表数量都有限制。总得来说,这些方案都不是十分的理想,多多少少都存在一些缺点,这也从一个侧面反映出了Sharding扩容的难度。

ID问题

一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区数据库自生成的ID无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路由.

一些常见的主键生成策略

UUID

使用UUID作主键是最简单的方案,但是缺点也是非常明显的。由于UUID非常的长,除占用大量存储空间外,最主要的问题是在索引上,在建立索引和基于索引进行查询时都存在性能问题。

Twitter的分布式自增ID算法Snowflake

在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位 机器ID 10位 毫秒内序列12位。

跨分片的排序分页

一般来讲,分页时需要按照指定字段进行排序。当排序字段就是分片字段的时候,我们通过分片规则可以比较容易定位到指定的分片,而当排序字段非分片字段的时候,情况就会变得比较复杂了。为了最终结果的准确性,我们需要在不同的分片节点中将数据进行排序并返回,并将不同分片返回的结果集进行汇总和再次排序,最后再返回给用户。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9242257.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存