MySQL听讲(六)——查询

说到查询,首先想到了的是索引。本节基于MySQL听讲(三)——索引 的基础来对查询进行展开。

mysql索引选择策略

首先,我们必须了解到,mysql在选择索引时,优化器会从以下角度来考虑是否选择索引:

  • 使用force index(a-name)会强制使用a-name的索引(强制);
  • 根据统计条件对应的行数(行数越少越好,占用的CPU资源就少);
  • 根据是否排序,及其排序要花费的时间;
  • 回表的代价。

下面来逐条讲解一下每条需要注意的情况:
除了第一条是强制执行某索引,其他条都是综合考虑,通过估值来确定是否选择索引以及选择哪个索引的问题。

第二条,mysql在选择行数时,会采样统计[1],根据统计信息估算在查询条件的范围内大概有多少条记录。而这个时候就需要依靠于索引的区分度,一个索引上不同的值越多,其区分度就越好。
所以在建立索引(或者前缀索引)时,既要考虑索引的占用页数大小,也要考虑索引的使用效能,即区分度。

第三条,因为索引都是排好序的,所以有索引的可以直接忽略掉这部分花费的时间的考虑。如果一个查询语句中,order by和where中都有的字段,会更偏向于该字段的索引,尽管此时where中有别的索引有更优的效果。
ps:
[1] 采样统计:因为整表统计代价太大,所以选择采样统计。而采样统计会默认选择N个数据页,统计这些页上不同值,得到一个均值,再乘以这个索引的页数,就得到了这个索引的基数。而当数据库变更数据超过1/M时,会自动重新做一次索引统计。参数为innodb_stats_persistent,为on表示统计信息会持久化,此时默认N=20,M=10;为off时表示统计信息只存储于内存中,此时默认N=8,M=16。可以执行ANALYZE TABLE t;手动校正。

示例一
有索引index(a),index(b),在where (a between 1 and 1000) and (b between 10000 and 20000) order by b limit 1中,索引会选取b,而此时a才是更好的索引方案。所以可以修改为order by b,a limit 1。这种修改要确保想拿的数据还是原来的那条数据。
而如果没有limit 1,则b才是最好的方案。
因为索引都是排好序的,在a中选择1000条数据后,在b中从20000开始找一条好了。

示例二
针对上面的情况,还可以执行强制索引。如上面的语句可以写为from t force(index(a)) where (a between 1 and 1000) and (b between 10000 and 20000) order by b limit 1

索引优化

MySQL是根据数据采样来选择使用哪个索引的。执行show index from test3;,出现下面的界面:


上面红框标注的字段Cardinality,表示索引的取样,即该索引有多少种不同的值。如果差距过大,即此处样本数据和实际的数据量差距过大,则索引失效。可以使用ANALYZE local TABLE test3;来修复(local为避免写入bin log)。

count

关于count(*),MyISAM将表的总行数存在磁盘上了,而InnoDB需要逐行统计。
InnoDB不放在磁盘上,与其事务有关。读的时候会生成一致性视图。

而count(1)效率大于count(id),count(1)是遍历整张表,但不取值,对于返回的每一行放一个数字“1”进去,判断不为空就累加。而count(id)是统计主键索引,取出id后判断不为空就累加。

所以,结论是count(*)≈count(1)>count(id)。

多表关联

多表关联分为以下几种情况:
下面的分析为两表连接,具体的多表连接,MySQL会根据整体情况进行考量。

  1. 在使用LEFT JOIN,RIGHT JOIN,且没有条件时:
    驱动表一般跟随方向走。即left的驱动表在左边,right的驱动表在右边。无论关联字段是否有索引。
  2. 其他的JOIN和情况:
    在有条件时:
  • 若有前表的条件,则驱动表为前表;反之,则为后表。
  • 若前后表的条件都有,则查看下面红框中的值cardinality,谁的关联字段的值大,驱动表就是哪一个。
    image.png

    一般情况,都是小表驱动大表(N+λN*logM,N为小表扫描行数,M为大表总行数,λ为大表扫描索引次数)。

索引失效的情况

  • 对索引字段使用函数;
  • 索引里有null;
  • 对索引使用表达式[0];
  • 隐式类型转换[1];
  • 隐式字符集转换[2];
  • 日期类型不能使用in+字符串[3];
  • 对索引使用like'%xxx'或者like'%xxx%';
  • 对联合索引跨列使用;
  • 对联合索引没有依照最左原则使用。

ps:[0]:如id +1=10,要表达成id=9,否则索引失效。
[1]:MySQL会对字段类型进行转换,但也只是将字符串转成数字。而转换的一方很有可能是索引字段的一方,所以此时索引就失效了。日期和字符串除外。
[2]:MySQL在多表关联时会对字符集进行转换,一般会转换为其父字符集。如utf8转换为utfmb4。
[3]:针对于日期和字符串类型的比较运算,字符串会强制转换为日期,但是in里面如果是字符串,则不会使用索引。

慢查询

指查询超过指定参数long_query_time对应的时间的查询。该值在my.cnf中有,也可以手动设值,set long_query_time=0,表示超过0秒的查询记为慢查询。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • MYSQL 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 MySQL基本操...
    Kingtester阅读 7,809评论 5 116
  • 什么是数据库? 数据库是存储数据的集合的单独的应用程序。每个数据库具有一个或多个不同的API,用于创建,访问,管理...
    chen_000阅读 4,035评论 0 19
  • 今天看到一位朋友写的mysql笔记总结,觉得写的很详细很用心,这里转载一下,供大家参考下,也希望大家能关注他原文地...
    信仰与初衷阅读 4,730评论 0 30
  • 说起MySQL的查询优化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *、不使用NULL字段、合理创建索引、...
    怦然心_动阅读 431评论 1 4
  • MYSQL应该是最流行的WEB后端数据库。大量应用于PHP,Ruby,Python,Java 等Web语言开发项目...
    smooth00阅读 2,292评论 0 16