让查询飞起来:基于索引的 SQL 优化技巧

数据库 MySQL
基于索引的 SQL 优化旨在通过合理设计和使用索引来提升查询性能。索引可以加速数据检索,减少全表扫描,特别是在处理大量数据时。

1. 前言

今天,小编给大家分享点干货,工作中都能用到的东西。是什么呢?那就是Mysql的性能优化,我们一起来看看吧。

2. 优化方式

好的,现在我们先来看看有哪些优化方式,然后再这些优化方式当中,我们程序员需要掌握其中的哪些优化方式。

数据库层面的优化

  1. 表的结构是否正确?三范式
  2. 是否有正确的索引来提高查询效率?索引
  3. 是否为每个表使用了适当的存储引擎?存储引擎
  4. 每个表是否使用适当的行格式?字段压缩方式
  5. 是否使用了适当的锁策略?事务的隔离级别
  6. 用于缓存的所有内存区域的大小是否正确?buffpool

硬件层面的优化

  1. 硬盘
  2. cpu
  3. 内存宽带

上面这些优化方式,是mysql官网里面有的。针对这些优化点,对于我们程序员来说,是不是只需要关注数据库层面的优化。数据库层面的优化中我们是不是只需要着重关注索引的优化,所以今天小编会分享一些索引方面的优化点。

3. 慢日志查询

知道了优化点,那我们为什么要优化呢?肯定是执行时间太慢,并发能力上不去。所以,我们需不需要优化就需看我们执行的时间是否满足我们的需求。那我们怎么知道执行时间是否满足我们的需要呢?这个就要看我们的慢日志了。

慢日志参数:

  • long_query_time: 超过多少秒进入慢查
SELECT @@long_query_time;--默认是10单位S
SET GLOBAL long_query_time=1;--设置超过1s就算慢查
  • min_examined_row_limit: 检索查询的数量的行如果低于这个值,不进入慢查。
SELECT @@min_examined_row_limit;--默认是0
  • log_output: 慢日志保存方式
SELECT @@1og_output;--慢查存在哪里
SET GLOBAL log_output='table,file'; -- table:表 file:文件

如果是file,那么保存的文件路径为slow_query_log_file。

SELECT @aslow_query_log_file; -- 查询慢日志存放路径
SET GLOBAL slow_query_log_file=''; -- 设置慢日志存放路径

如果是table,则保存在mysql.slow_log表中。

  • slow_query_log:  慢日志开关
SELECT @@slow_query_log; -- 查询慢日志开关
SET GLOBAL slow_query_log=1; -- 开启慢查

4. sql语句优化

Explain执行计划

建立索引建立在where、orderby、groupby的字段上面,提升查询性能;但是就算加了也不一定能走到索引,所以要学会Explain分析。

Explain输出字段

这些字段里面,我们只关注里面几个就行了。

  • type列:  这一列显示了访问类型,即MySQL决定如何查找表中的行。
    依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL。
    这个我们需要优化到 range 级别。
EXPLAIN select * FROM product WHERE id=1; -- const 只有一个匹配行并且id是主键
EXPLAIN select product_price FROM product WHERE product_price=55 -- ref 查询非唯一索引或主键的索引值
EXPLAIN select * FROM product WHERE id in(1,2); -- range 范围扫描
EXPLAIN SELECT * FROM product INNER JOIN product_price on product_new.id=product.product_id; -- eq_ref 组合查询中,用到了主键或者唯一索引
EXPLAIN SELECT product_price FROM product ORDER BY product_price; -- index类型 扫描索引树 比all相对来讲要快
EXPLAIN SELECT product_tag FROM product ORDER BY product_tag; -- all 不是索引,没有对应的索引树一般数据量大的情况下是需要优化的
  • possible_keys: 可以选择的索引查询,如果为null则没有索引可以供选择。
  • key: 真正使用的索引
  • rows: 执行查询必须扫描的行数,对于InnoDB来讲,这个是个预估值,不是非常准确,但是行数越少,性能肯定越好。
  • Extra

Using filesort: 排序没有走到索引

Using index 在索引树中能遍历到想要的数据(覆盖索引)

Using index condition 索引条件下推

Using index for group-by group by分组基于索引检索

Using temporary 是否使用临时表,一般在 group by与order by场景

Using where 扫描出来的数据需要进行where匹配

order by优化

如果让orderby的字段走索引,那么排序流程直接可以在索引树完成,如果排序的字段不走索引,整个排序流程必须先把数据放到内存,在内存实现排序。

怎么判断是否orderby用到了索引?

如果输出Extra的列 EXPLAIN 不包含 Using filesort,则使用了索引

如果输出Extra列 EXPLAIN 包含 Using filesort,则没有使用索引

count优化

count()是一个聚合函数,对于返回的结果集 的一个统计,一行一行去判断,如果count括号里的不是null,那么计值+1,否则不加,最后返回一个累计的总数。

count(*):* 是整条数据,也进行了优化,因为整条数据肯定不会为null。所以也不需要去判断

count(1):1 是扫描到数据 扫描到了就固定返回一个1,肯定不为null,不会做null判断。

count(id):id 主键id,肯定不为null,也不会去判断null,但是相对于count(1)来讲,要去解析ID。稍微慢点,但是也可以忽略不计。

count(字段):这个就有影响了,因为扫描行出来,需要判断字段是否为空。

Limit优化

limit m,n ; 扫描m+n条数据,然后过滤掉前面的m条数据,当m越大,那么需要扫描的数据也就越多,性能也会越来越慢。

EXPLAIN SELECT * FROM product LIMIT 100000,10 --很慢很慢

针对这种情况,有以下几种方案可以进行一定的优化。

  • 如果id是趋势递增的,那么每次查询都可以返回这次查询最大的ID,然后下次查询,加上大于 上次最大id的条件,这样会通过主键索引去扫描,并且扫描数量会少很多很多。因为只需要扫描where条件的数据
SELECT * FROM product WHERE id > 100000 ORDER BY id LIMIT 10 -- 根据id查询,并且使用where过滤
  • 先limit出来主键ID,然后用主表跟查询出来的ID进行inner join 内连接,这样,也能一定上提速,因为减少了回表,查询ID只需要走聚集索引就行。
SELECT * FROM product INNER JOIN(
 SELECT id FROM product ORDER BY id LIMIT 100000,10
) a
ON product_new.id=a.id

分库分表

如果sql语句用到了索引,但是查询还是很慢,那么看看数据库表中的数据是否过多或者并发是不是很高。如果并发很高,那么我们可以考虑分库,比如order和product,把业务细化。如果表数据过多,那就需要分表,当然我们也可以引入第三方组件解决数据过多的问题,比如Elasticsearch。

5. 总结

对于上面的优化,基本上都是基于索引的。基于索引的 SQL 优化旨在通过合理设计和使用索引来提升查询性能。索引可以加速数据检索,减少全表扫描,特别是在处理大量数据时。优化策略包括选择合适的索引类型(如单列索引、复合索引)、避免冗余索引、使用覆盖索引来避免访问表数据、并通过 EXPLAIN 分析查询执行计划来确保索引的有效使用。合理设计索引不仅能加速查询,还能减少数据库负担,提高整体性能。

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2019-03-25 08:05:35

Elasticsear优化集群

2021-07-13 07:52:03

SQL面试COUNT(*)

2023-11-10 18:03:04

业务场景SQL

2020-09-29 07:54:05

Express 飞起

2011-04-13 10:51:58

MATLAB

2011-05-20 11:12:01

数据库DB2优化

2023-03-01 23:59:23

Java开发

2024-06-12 12:28:23

2011-05-11 11:32:35

数据库DB2优化技巧

2022-10-09 18:14:31

订单系统分库分表

2019-11-05 10:35:57

SpringBoot调优Java

2011-02-25 08:39:11

QFabric数据中心Juniper

2013-01-07 09:34:43

CodeLoveBAT

2016-01-19 17:03:59

数据中心网络华为

2011-09-27 13:25:05

Web

2024-11-25 18:00:00

C#代码编程

2016-05-11 09:18:21

AWS云数据仓库Redshift

2021-01-04 15:11:57

开发 IDEA代码

2009-03-20 14:18:38

机房数据传输安全

2023-03-31 15:10:32

PythonVSCode程序员
点赞
收藏

51CTO技术栈公众号