MySQL高级知识-查询与索引优化分析

性能下降SQL慢、执行时间长、等待时间长

  • 查询语句写的烂
  • 索引失效
    • 单值索引
    • 复合索引
  • 关联查询太多join(设计缺陷或不得已的需求,除非你能干的过你的产品经理)
  • 服务器调优及各个参数设置(缓冲、线程数等)

常见通用的Join查询

SQL执行顺序
  • 手写
    • 手写SQL顺序
SELECT DISTINCT
    <select_list>
FROM
     <left_table> <join_type>
JOIN <right_table> ON <join_condition>
WHERE 
    <where_condition>
GROUP BY
    <group_by_list>
HAVING
    <having_condition>
ORDER BY
    <order_by_condition>
LIMIT <limit_number>
  • 机读(MySQL读取顺序)
    • 机读顺序
FROM
     <left_table>
ON <join_condition>
<join_type> JOIN <right_table> 
WHERE 
    <where_condition>
GROUP BY
    <group_by_list>
HAVING
    <having_condition>
SELECT DISTINCT
    <select_list>
ORDER BY
    <order_by_condition>
LIMIT <limit_number>
  • 总结-SQL解析顺序
    • SQL解析
SQL JOINs
  • 七种JOIN图解
  • 实验:
-- 建表和数据SQL
CREATE TABLE `tbl_dept` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `deptName` VARCHAR(30) DEFAULT NULL,
 `locAdd` VARCHAR(40) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
CREATE TABLE `tbl_emp` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(20) DEFAULT NULL,
 `deptId` INT(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `fk_dept_id` (`deptId`)
 #CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `tbl_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
 
 
INSERT INTO tbl_dept(deptName,locAdd) VALUES('RD',11);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('HR',12);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('MK',13);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('MIS',14);
  • 练习
    • 1、A、B两表共有
      • select * from tbl_emp a inner join tbl_dept b on a.deptId = b.id;
    • 2、A、B两表共有+A的独有
      • select * from tbl_emp a left join tbl_dept b on a.deptId = b.id
    • 3、A、B两表共有+B的独有
      • select * from tbl_emp a right join tbl_dept b on a.deptId = b.id;
    • 4、A的独有
      • select * from tbl_emp a left join tbl_dept b on a.deptId = b.id where b.id is null;
    • 5、B的独有
      • select * from tbl_emp a right join tbl_dept b on a.deptId = b.id where a.deptId is null;
    • 6、AB全有
      • MySQL Full Join的实现 因为MySQL不支持FULL JOIN,下面是替代方法
      • left join + union(可去除重复数据)+ right join
      • 实现如下面代码
    • 7、A的独有 + B的独有
-- 6、AB全有
SELECT *
FROM tbl_emp a LEFT JOIN tbl_dept b ON a.deptId = b.id
UNION 
SELECT *
FROM tbl_emp a RIGHT JOIN tbl_dept b ON a.deptId = b.id;


-- 7、A的独有 + B的独有
SELECT *
FROM tbl_emp a LEFT JOIN tbl_dept b ON a.deptId = b.id
WHERE b.id IS NULL
UNION
SELECT *
FROM tbl_emp a RIGHT JOIN tbl_dept b ON a.deptId = b.id
WHERE a.`deptId` IS NULL;

索引简介

什么是索引
  • MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构
    • 可以得到索引的本质:索引是数据结构
    • 索引的目的在于提高查询效率,可以类比字典,
    • 如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql。
    • 如果没有索引,那么你可能需要a----z,如果我想找到Java开头的单词呢?或者Oracle开头的单词呢?
    • 是不是觉得如果没有索引,这个事情根本无法完成?
  • 你可以简单理解为“排好序的快速查找结构”
    • 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,
      这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
    • 下图就是一种可能的索引方式示例:
    • 为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。
  • 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上
  • 我们平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。其中聚集索引,次要索引,覆盖索引,
    复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引
    。当然,除了B+树这种类型的索引之外,还有哈稀索引(hash index)等。
索引的优势
  • 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
  • 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
索引的劣势
  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的
  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息
  • 索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句
MySQL索引分类
  • 单值索引
    • 即一个索引只包含单个列,一个表可以有多个单列索引
  • 唯一索引
    • 索引列的值必须唯一,但允许有空值
  • 复合索引
    • 即一个索包含多个列
  • 基本语法
    • 创建,两种方式
      • CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));
        • 如果是CHAR,VARCHAR类型,length 可以小于字段实际长度;
        • 如果是 BLOB 和 TEXT 类型,必须指定 length。
      • ALTER mytable ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
    • 删除
      • DROP INDEX [indexName] ON mytable;
    • 查看
      • SHOW INDEX FROM table_name\G
    • 使用Alter 命令
      • 有四种方式来添加数据表的索引:
        • ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)
          • 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
        • ALTER TABLE tbl_name ADD UNIQUE index_name (column_list)
          • 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
        • ALTER TABLE tbl_name ADD INDEX index_name (column_list)
          • 添加普通索引,索引值可出现多次。
        • ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list)
          • 该语句指定了索引为 FULLTEXT ,用于全文索引。
MySQL索引结构
  • BTree索引
    • 检索原理
      • 【初始化介绍】
        • 一颗b+树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项深蓝色所示)和指针黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3。 P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。
        • 真实的数据存在于叶子节点即 3、5、9、10、13、15、28、29、36、60、75、79、90、99。
        • 非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。
      • 【查找过程】
        • 如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。
        • 真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容