索引实效情况

2024-06-03 17:08
文章标签 索引 情况 实效

本文主要是介绍索引实效情况,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

索引失效&子查询-慢查询的起因

原创   2015年07月11日 22:06:52
  • 2827

目前,Mysql作为常用的数据库,在各类业务中被广泛运用。但是其设计并非是十全十美,一些我们认为“高效“的语句,在执行时会花费大量的时间,导致页面出现超时错误。

这里举一些简单的bad case,希望大家以后处理慢sql时能有所参考。(不想研究分析过程的,请移步总结)


子查询是一个坑

业务中,我们定义了两张表:用户参加项目表(user_project)和用户公会情况表(union_user)。user_project表中有user_id和project_id字段来标记用户参与项目的对应关系,同时这两个字段都为索引。而union_user表中有user_id和union_id字段来标记用户属于哪个公会,这两字段也全为索引。

那么假设我们需要查询一个“某公会的用户参与了哪一些项目“时,自然而然会想到用这样的语句进行查询:

[sql]  view plain  copy
  1. SELECT * FROM user_project   
  2. WHERE user_id in   
  3. (SELECT user_id FROM union_user WHERE union_id=1)  

在我们的想象中,查询应该是这样的:

同时,查询中用到的键都建立了索引,所以应该相当快吧!?

但是事实上,这条语句执行的效率相当之差,执行一次花费的时间在10s以上。那么问题出在哪里呢?

我们使用测试库来分析一下这条语句:


可以发现user_project没有使用user_id这个键进行查询,遍历了表中所有的4条记录。

索引为啥没有起效呢?这里就要介绍两个知识点了:

  • 第一个为Mysql在处理所有的查询的时候都强行转换为联接来执行,将每个查询包括多表中关联匹配,关联子查询,union,甚至单表的的查询都处理为联接,接着Mysql执行联接,把每个联接在处理为一个嵌套循环;
  • 第二个知识点:在Mysql在处理子查询的时候,会将子查询改写,Mysql将会扫描外查询中的所有数据,每条数据都将会传到子查询中进行关联,子查询不能首先被执行,如果外表很大的话,那么性能上将会出现问题。

事实上,我们的查询语句被Mysql转化成如下格式进行执行:

[sql]  view plain  copy
  1. SELECT * FROM `user_project`   
  2. WHERE EXISTS   
  3. (SELECT * FROM union_user   
  4. where union_id=1   
  5. and union_user.user_id=user_project.user_id)   

分析其执行过程,可以发现是不会经过user_id索引的:


如何避免子查询的这一问题呢?直接使用联表查询即可:

[sql]  view plain  copy
  1. SELECT * FROM `user_project`  
  2.  INNER JOIN union_user using (user_id)  
  3.  where union_id=1  

分析该语句,发现有效使用了user_id的索引,查询遍历的行数大大降低。

索引失效的一些case

1.           使用OR

SQL如下:

[sql]  view plain  copy
  1. SELECT * FROM `user_project` where id=1 or user_id=1  

虽然查询所用的字段都是索引,但是最终mysql并没有使用其中任何一个。


2.           like查询是以%开头

SQL如下:

[sql]  view plain  copy
  1. SELECT * FROM `userWHERE `user_name` LIKE 'abc%'  

能够正确使用索引:


SQL修改为:

[sql]  view plain  copy
  1. SELECT * FROM `userWHERE `user_name` LIKE '%abc'  

查询时就会不使用索引


3.           查询字符型不用引号

如果代码使用拼串去写语句,同时根据数据的类型决定是否加上引号,那么会构造出这样的语句:

[sql]  view plain  copy
  1. SELECTFROM `userWHERE user_name=123  

而这样的语句实际上是不走索引的:


所以建议还是使用bind来进行参数传递,预防注入的同时,避免这种坑爹问题。

4.           多列索引不查询前一部分

表中的有一个多列索引status,用到了status和score两个字段:


如果只查询status,那么索引是有效的


但是只查询score这一字段,不去查status,那么这个多列索引并不会起效:

总结

总结一下以上的坑:

  • 尽量使用联表查询来替代子查询,因为使用子查询会使索引失效;
  • 查询条件中谨慎使用or;
  • 多列索引设置时请考虑好使用场景,如果有只查其中部分字段的情况,该索引可能不会生效;
  • 查询字符型时请加上引号,确保使用索引;
  • 以%开头的like查询不会走索引。

这篇关于索引实效情况的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

贝壳面试:什么是回表?什么是索引下推?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题: 1.谈谈你对MySQL 索引下推 的认识? 2.在MySQL中,索引下推 是如何实现的?请简述其工作原理。 3、说说什么是 回表,什么是 索引下推 ? 最近有小伙伴在面试 贝壳、soul,又遇到了相关的

Mysql高级篇(中)——索引介绍

Mysql高级篇(中)——索引介绍 一、索引本质二、索引优缺点三、索引分类(1)按数据结构分类(2)按功能分类(3) 按存储引擎分类(4) 按存储方式分类(5) 按使用方式分类 四、 索引基本语法(1)创建索引(2)查看索引(3)删除索引(4)ALTER 关键字创建/删除索引 五、适合创建索引的情况思考题 六、不适合创建索引的情况 一、索引本质 索引本质 是 一种数据结构,它用

如何保证android程序进程不到万不得已的情况下,不会被结束

最近,做一个调用系统自带相机的那么一个功能,遇到的坑,在此记录一下。 设备:红米note4 问题起因 因为自定义的相机,很难满足客户的所有需要,比如:自拍杆的支持,优化方面等等。这些方面自定义的相机都不比系统自带的好,因为有些系统都是商家定制的,难免会出现一个奇葩的问题。比如:你在这款手机上运行,无任何问题,然而你换一款手机后,问题就出现了。 比如:小米的红米系列,你启用系统自带拍照功能后

Windows11电脑上自带的画图软件修改照片大小(不裁剪尺寸的情况下)

针对一张图片,有时候上传的图片有大小限制,那么在这种情况下如何修改其大小呢,在不裁剪尺寸的情况下 步骤如下: 1.选定一张图片,右击->打开方式->画图,如下: 第二步:打开图片后,我们可以看到图片的大小为82.1kb,点击上面工具栏的“重设大小和倾斜”进行调整,如下: 第三步:修改水平和垂直的数字,此处我修改为分别都修改为50,然后保存,可以看到大小变成63.5kb,如下:

ElasticSearch 6.1.1 通过Head插件,新建索引,添加文档,及其查询数据

ElasticSearch 6.1.1 通过Head插件,新建索引,添加文档,及其查询; 一、首先启动相关服务: 二、新建一个film索引: 三、建立映射: 1、通过Head插件: POST http://192.168.1.111:9200/film/_mapping/dongzuo/ {"properties": {"title": {"type":

ElasticSearch 6.1.1运用代码添加索引及其添加,修改,删除文档

1、新建一个MAVEN项目:ElasticSearchTest 2、修改pom.xml文件内容: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.or

postgres数据库中如何看查询是否走索引,以及在什么情况下走索引

在 PostgreSQL 中,可以通过 EXPLAIN 或 EXPLAIN ANALYZE 查看查询计划,以判断查询是否使用了索引。除此之外,了解索引的使用条件对于优化查询性能也很重要。 1. 如何查看查询是否使用索引 使用 EXPLAIN 查看查询计划 EXPLAIN 显示 PostgreSQL 如何执行查询,包括是否使用索引。 EXPLAIN SELECT * FROM users WH

数据库系统 第42节 数据库索引简介

数据库索引是数据库表中一个或多个列的数据结构,用于加快数据检索速度。除了基础的B-Tree索引,其他类型的索引针对特定的数据类型和查询模式提供了优化。以下是几种不同类型的索引及其使用场景的详细说明和示例代码。 1. 位图索引 (Bitmap Index) 位图索引适用于具有少量不同值的列(例如性别、国家代码等),它使用位图来表示数据,从而提高查询效率。 适用场景:当列中的值域较小,且数据分布

linux 查看内存使用情况

Linux查看CPU和内存使用情况:http://www.cnblogs.com/xd502djj/archive/2011/03/01/1968041.html 在做Linux系统优化的时候,物理内存是其中最重要的一方面。自然的,Linux也提供了非常多的方法来监控宝贵的内存资源的使用情况。下面的清单详细的列出了Linux系统下通过视图工具或命令行来查看内存使用情况的各种方法。 1. /pr