0

如题, 我一直以为 select * from 表 where 索引列=xx and 非索引列=yy 一定会走索引列的索引.
但是今天发现, 并不是这样.
经测试(MySQL 5.6.16):

  1. 当联合条件能够匹配到记录时, 索引.
  2. 当联合条件不能匹配到记录时, 不走索引.

按照我的预期, mysql优化器用索引列扫描, 没有找到, 直接返回不就得了, 不用再管后面的非索引列了.
但是, 按照上面的测试来看, 很有可能是, 先走索引列, 发现没有对应的记录, 然后全表扫描了下.

另外, 即使使用了force index (索引列的索引)依旧是上面的情形.

示例:

id是索引列, content_type是非索引列.

联合条件匹配无记录时

clipboard.png

联合条件无匹配记录时

clipboard.png

测试表的结构

clipboard.png

开启prifiling后

执行SQL:
select sql_no_cache * from 表 force index(primary) where id=5 and content_type='电话'; (联合条件匹配不到记录的场景)

查看profile信息:
clipboard.png

Nisus 92
2018-12-07 提问
2 个回答
1

已采纳

你这个例子怎么看出没用索引呢?你的id和content_type列都属于主键索引的索引内容,也就是说,你的查询是在一个const table里面进行,所以查不到数据会显示Impossible WHERE noticed after reading const tables。其他情况一般是显示using where的。
这里的Impossible WHERE是告诉你,在主键索引里,没找到你想要的行,主键也是索引呢,别歧视他,老铁。
另外,你要做实验,应该用非主键索引来弄。

1

开启 profiling 后再执行看看, explain 和真实执行的可能不一样, 从截图上看 id 是主键并且是等值查询,会走索引才对, 把表结构拿出来看看

profiling开启方法

# 开启
set profiling = 1

# 执行语句
...

# 查看所有语句
show profiles

# 查看语句具体的执行情况
show frofile for query query_number

====== 回复分割线 =======

上面说错一个地方,profiling 能看到执行使用资源,不能看到是否用索引

我在 5.7 版本(刚好测试环境有)下执行这个查询语句:

Extra 显示的是 no matching row in const table

然后去官网看了一下 explain 的输出解析

意思就是在唯一索引里面找不到相应的数据, 文档里面有说用到索引去查询,至于怎么证明,还没想到

1

插入数据本来就是比较慢的过程,很吃系统 IO
我们在做大量插入的时候,想要在数据库层面提高性能:

  1. 设置不记录二进制日志 ,如果没有做主从可以这样操作: SET sql_log_bin=0
  2. 设置忽略外键约束: SET FOREIGN_KEY_CHECKS=0
  3. 设置忽略二级索引的唯一性约束: SET UNIQUE_CHECKS=0
  4. innodb 日志每次 commit 刷新改为每秒(配置文件改): innodb_flush_log_at_trx_commit=2
  5. 单个 commit 改为批量 commit,比如 100 条 commit 一次

程淇铭 · 12月7日

展开评论

撰写答案

你可能感兴趣的

推广链接