标签:高级 查询 索引 Mysql null where id select
1 mysql高级 2 ”练武不练功,到老一场空,认认真真练一遍,今天多学一门技术,明天少说一句求人的话;高新12k以上的岗位一定会靠你sql“ 3 “DBA每天做索引重建工作,锁表重建索引” 4 “物理删除改为逻辑删除,其一,大数据时代保留数据,以便分析;其二,为了索引” 5 “运维问题,数据说话,理工类工作严禁我觉得” 6 “程序员分两种:15k以下的只能完成功能;撑死优秀完成功能15-20;20以上的不但能完成功能也能搞定性能” 7 8 1、mysql的架构介绍 9 1.1Mysql简介 10 1.1.1概述 11 12 1.1.2高级Mysql(完整的mysql优化需要很深的功底,大公司甚至有专门的DBA写上述) 13 1.1.2.1mysql内核 14 1.1.3sql优化工程师 15 1.1.4mysql服务器优化 16 1.1.5各种参数常量设定 17 1.1.6查询语句优化 18 1.1.7主从复制 19 1.1.8软硬件升级 20 1.1.9容灾备份 21 1.1.10sql编程 22 23 1.2Mysqllinux版安装 24 1.2.1 mysql5.5rpm 25 1.2.1.1 下载地址 26 http://dev.mysql.com/downloads/mysql/,下载ga版 27 1.2.1.2 检查当前系统是否安装过mysql 28 rpm -qa|grep -i mysql 29 1.2.1.3 安装mysql服务端(注意提示) 30 cd /opt (linux尽量不含中文不含空格) 31 rpm -ivh MySQL-server-5.5.48-1.linux2.6.i386.rpm 32 注意修改密码 33 1.2.1.4 安装mysql客户端 34 rpm -ivh MySQL-client-5.5.48-1.linux2.6.i386.rpm 35 1.2.1.5 查看mysql安装时创建的mysql用户和mysql组 36 ps -ef|grep mysql 37 cat /etc/passwd |grep mysql 38 cat /etc/group |grep mysql 39 mysqladmin --version 40 1.2.1.6 mysql服务的启+停 41 service mysql start|stop|restart 42 ps -ef|grep mysql 43 top 可以从服务器启动持续时间一定判断该公司研发部的水准,经常关的要注意 44 1.2.1.7 mysql服务启动后,开始连接 45 /usr/bin/mysqladmin -u root password 123456 46 首次连接成功 47 注意这里,因为Mysql默认没有密码,所以这里我们没有输入密码就直接连上了 48 按照安装server中的提示修改登录密码 49 1.2.1.8 自启动mysql服务 50 chkconfig mysql on 51 chkconfig --list | grep mysql 52 cat /etc/inittab inittab is no longer used when using systemd. 53 ntsysv 图形显示开机启动 54 1.2.1.9 修改配置文件位置 55 cd /usr/share/mysql/ 56 cp my-huge.cnf /etc/my.cnf 57 1.2.1.10 修改字符集合数据存储路径 58 show variables like 'character%'; 59 show variables like '%char%'; 60 默认客户端和服务器都用了latin1所以会乱码。5.7是character_set_server=utf8一个,和5.5有区别 61 在字符集修改之前创建的库没有收到配置文件影响,最好安装mysql之后立即修改字符集 62 1.2.1.11 mysql的安装位置 63 在linux下查看安装目录 ps -ef | grep mysql 64 /var/lib/mysql #数据库文件的存放位置 65 /usr/share/mysql #主管配置文件的目录 66 /usr/bin #相关命令 67 /etc/init.d/mysql #启停脚本相关 68 69 1.3Mysql配置文件 70 主要配置文件: 71 1.3.1 二进制日志log-bin 72 主要用于主从复制 73 1.3.2 错误日志log-error 74 -默认是关闭的,记录严重的警告和错误信息,每次启动和关闭时候的详细信息 75 76 1.3.3 查询日志log 77 -默认是关闭的,记录查询的sql语句,如果开启会减低mysql的整体性能,因为记录日志也是消耗系统资源的 78 1.3.4 数据文件 79 两系统 80 windows 81 D:\devSoft\MySQLServer5.5\data目录下可以挑选很多库 82 linux 83 看看当前系统中的全部库后再进去 ls -lF|grep ^d 84 默认路径:/var/lib/mysql 85 frm文件 86 存放表结构 87 myd文件 88 存放表数据 89 myi 90 存放索引表 91 92 1.3.5 如何配置 93 windows -my.ini文件 94 显示的配置: 95 log-bin= 96 log-error= 97 linux -/etc/my.cnf文件 98 1.4Mysql逻辑架构 99 1.4.1总体概览 100 ①连接层(jdbc,native c api) 101 ②服务层 -业务逻辑处理层 102 ③引擎层 -数据存储引擎 103 ④存储层 -文件存储层 104 插件式的存储引擎设计将查询和其它的系统任务以及数据处理提取相分离 105 106 1.4.2查询说明 107 1.5Mysql存储引擎 108 1.5.1 查看命令 109 show engines;#支持哪些存储引擎 110 show variables like '%storage_engine%';#当前的存储引擎 111 1.5.2 MyISAM和InnoDB 112 对比项 MyISAM InnoDB 113 主外键 不支持 支持 114 事务 不支持 支持 115 行锁表 表锁,即使操作一条记录也会锁住整个表,不适合高并发操作 行锁,操作时只锁住某一行,不对其他行有影响,适合高并发 116 缓存 只缓存索引,不缓存真实数据 不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性影响 117 表空间 小 大 118 关注点 性能 事务 119 默认安装 Y Y 120 1.5.3 阿里巴巴、淘宝用哪个 121 产品 价格 目标 主要功能 是否投入生产 122 Percona Server 免费 提供XtraDB存储引擎的包装器和其他分析工具 XtrDB 是 123 MariaDB 免费 124 Drizzle 免费 125 2、索引优化分析 126 2.1性能下降SQL慢、执行时间长,等待时间长 127 2.1.1查询语句写的烂 128 2.1.2索引失效 129 单值索引 130 select * from user where name='';create index idx_user_name on user(name); 131 复合索引 132 select * from user where name='' and email='';create index idx_user_nameEmail on user(name,email); 133 2.1.3关联查询太多join(设计缺陷或不得已的需求) 134 135 2.1.4服务器调优及各参数设置(缓冲、线程数等) 136 137 2.2常见通用的join查询 138 2.2.1SQL执行顺序 139 手写 140 机读 141 总结 142 2.2.2join图 143 (画圆形图理解,直观) 144 内连接(共有部分) SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.Key = B.Key; 145 左连接 (AB共有+A的独有) SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key; 146 右连接(AB共有+B的独有) SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key; 147 左外链接(A独有) SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key WHERE B.Key IS NULL; 148 右外连接(B独有) SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL; 149 全连接(A+B) SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.Key = B.Key; (mysql不支持) 150 全外连接(独A+独B) SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL OR B.Key IS NULL ; 151 2.2.3建表SQL 152 creat database db0629; 153 CREATE TABLE `tbl_dept`( 154 `id` INT(11) NOT NULL AUTO_INCREMENT, 155 `deptName` VARCHAR(30) DEFAULT NULL, 156 `locAdd` VARCHAR(40) DEFAULT NULL, 157 PRIMARY KEY(`id`) 158 )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 159 160 CREATE TALBLE `tbl_emp`( 161 `id` INT(11) NOT NULL AUTO_INCREMENT, 162 `name` VARCHAR(20) DEFAULT NULL, 163 `deptId` INT(11) DEFAULT NULL, 164 PRIMARY KEY(`id`), 165 KEY `fk_dept_id`(`deptId`) 166 #CONSTRAINT `fk_dept_id` FOREIGN KEY(`deptId`) REFERENCES `tbl_dept`(`id`) 167 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 168 169 INSERT INTO tbl_dept(deptName,locAdd) VALUES('RD',11); 170 INSERT INTO tbl_dept(deptName,locAdd) VALUES('HR',12); 171 INSERT INTO tbl_dept(deptName,locAdd) VALUES('MK',13); 172 INSERT INTO tbl_dept(deptName,locAdd) VALUES('MIS',14); 173 INSERT INTO tbl_dept(deptName,locAdd) VALUES('FD',15); 174 175 176 INSERT INTO tbl_emp(NAME,deptId) VALUES('z3',1); 177 INSERT INTO tbl_emp(NAME,deptId) VALUES('z4',1); 178 INSERT INTO tbl_emp(NAME,deptId) VALUES('z5',1); 179 INSERT INTO tbl_emp(NAME,deptId) VALUES('w5',2); 180 INSERT INTO tbl_emp(NAME,deptId) VALUES('w6',2); 181 INSERT INTO tbl_emp(NAME,deptId) VALUES('s7',3); 182 INSERT INTO tbl_emp(NAME,deptId) VALUES('s8',4); 183 INSERT INTO tbl_emp(NAME,deptId) VALUES('s9',51); 184 2.2.4 7种JOIN 185 全连接 186 select * from tbl_emp a left join tbl_dept b on a.deptId = b.id 187 union 188 select * from tb1_emp a right join tbl_dept b on a.deptId = b.id 189 全外连接 190 select * from tbl_emp a left join tbl_dept b on a.deptId = b.id where b.id is null; 191 union 192 select * from tb1_emp a right join tbl_dept b on a.deptId = b.id where a.deptId is null; 193 2.3索引简介 194 2.3.1 索引是什么 195 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构。 196 可以得到索引的本质:索引是数据结构 197 索引的目的在于提高效率,可以类比字典, 198 如果要查询“mysql”这个单词,我们肯定需要定位m字母,然后从上往下找到y字母,再找到剩下的sql 199 如果没有索引那么你可能需要a-z,如果我想找到java开头的单词呢:或者Oracle开头的单词呢? 200 是不是觉得如果没有索引,这个事情根本无法完成? 201 你可以简单理解为“排好序的快速查找数据结构” ☆ 202 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构基础上实现高级查找算法,这种数据结构就是索引。 203 204 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上 205 我们平常所说的索引,如果没有特别指明,都是值B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引 206 符合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引,当然,除了B+这种类型的索引之外,还有哈希索引(hash 207 index)等。 208 2.3.2 优势 209 类似大学图书馆建书目索引,提高数据检索的效率,降低数据的io成本; 210 通过索引列对数据进行排序,降低数据排序的成本,降低了cpu的消耗; 211 2.3.3 劣势 212 ①实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要占用空间的 213 ②虽然索引大大提过了查找的速度,同事却会降低更新表的速度,如对表进行insert,update和delete。 214 因为更新表时,Mysql不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段, 215 都会调整因为更新所带来的键值变化后的索引信息 216 ③索引只是提高效率的一个因素,如果你的mysql有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询 217 218 2.3.4 mysql索引分类 219 建议一张表的索引最多不要超过5个 220 ①单值索引 221 即一个索引只包含单个列,一个表可以有多个单列索引 222 ②唯一索引 223 索引列的值必须唯一,但允许为空值 224 ③复合索引 225 即一个所以不能包含过个列 226 ④基本语法 227 一、创建 228 CREATE 【UNIQUE】 INDEX indexName ON mytable(columnname(length)); 229 ALTER mytable ADD 【UNIQUE】INDEX 【indexName】ON(columnname(length)) 230 二、删除 231 DROP INDEX 【indexName】ON mytable; 232 三、查看 233 SHOW INDEX FROM table_name\G 234 四、使用alter命令 235 有四种方式添加数据表的索引 236 ALTER TABLE tbl_name ADD PRIMARY KEY(column_list);该语句添加了一个主键,这意味着索引值必须是唯一的,且不能为NULL。 237 ALTER TABLE tbl_name ADD UNIQUE index_name(column_list);这条语句创建的索引值必须是唯一的(除了NUll外,null可能出现多次)。 238 ALTER TABLE tbl_name ADD INDEX index_name(column_list);添加普通索引,索引值可以出现多次。 239 ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list);,该语句指定了索引为FULLTEXT,用于全文索引。 240 241 2.3.5 mysql索引结构 242 2.3.5.1 BTree索引 243 检索原理 244 真实的数据存在于叶子节点,非叶子节点只 不存真实的数据项,只存储指引搜索方向的数据项 245 2.3.5.2 Hash索引 246 2.3.5.3 full-text全文索引 247 2.3.5.4 R-Tree索引 248 2.3.6 哪些情况需要创建索引 249 2.3.6.1 主键自动建立唯一索引 250 2.3.6.2 频繁作为查询条件的字段应该创建索引 251 2.3.6.3 查询中与其它表关联的字段,外键关系建立索引 252 2.3.6.4 频繁更新的字段不适合创建索引 253 - 因为每次更新不单单是更新了记录还会更新索引 254 2.3.6.5 where条件里用不到的字段不创建索引 255 2.3.6.6 单键/组合索引的选择问题,who?(在高并发下倾向创建组合索引) 256 2.3.6.7 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度 257 2.3.6.8 查询中统计或者分组字段 258 2.3.7 哪些情况不需要创建索引 259 2.3.7.1 表记录太少 260 2.3.7.2 经常增删改的表 261 why:提高了查询速度,同事却会降低了更新表的速度,如对表进行insert、update和delete。 262 因为更新表时,Mysql不仅要保存数据,还要保存一下索引文件 263 2.3.7.3 数据重复且平均的表自短发,因此应该只为最经常查询的和最经常排序的数据列建立索引。 264 注意,如果某个数据列包含许多重复内容,为它建立索引就没有太大的实际效果 265 索引的选择性是指索引列中不同值的数目与表中记录的数的比。如果一个表中有2000条记录,表索引列 266 有1980个不通的值,那么这个索引的选择性就是1980/2000=0.99.一个索引的选择性越接近1,那么这个索引的效率就越高 267 268 269 2.4性能分析 ☆ 270 2.4.1 MySQL Query Optimizer 271 2.4.1.1 Mysql中有专门负责优化select语句的优化器模块,主要功能:通过计算分析系统中收到的统计信息,为客户端请求的Query提供他认为最优的执行计划 272 (他认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分最耗时间) 273 2.4.1.2 当客户端想Mysql请求一条Query,命令解析器模块完成请求分类,区别是SELECT并转发给Mysql Query Optimizer时,Mysql Query Optimizer首先会对整条query进行优化 274 ,处理掉一些常量表达式的预算,直接换算成常量值,并对query中的条件进行简化和转换,如果去掉一些无用和显而易见条件,结构调整等。然后分析Query中的Hint信息(如果有) 275 ,看现实Hint信息是否可以完全确定该query的执行计划,如果没有Hint或Hint信息还不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据query进行写相应的计算分析 276 ,然后再得出最后的执行计划。 277 278 2.4.2 MySQL 常见瓶颈 279 2.4.2.1 CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候 280 2.4.2.2 IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候 281 2.4.2.3 服务器硬件性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态 282 283 2.4.3 Explian 284 2.4.3.1 是什么(查看执行计划) 285 使用Explain关键字可以模拟优化器执行sql查询,从而知道mysql是 286 如何处理你的sql语句。分析你的查询语句或是表结构的性能瓶颈 287 官网介绍 288 289 2.4.3.2 能干嘛 290 2.4.3.2.1 表的读取顺序 291 2.4.3.2.2 数据读取操作的操作类型 292 2.4.3.2.3 哪些索引可以使用 293 2.4.3.2.4 哪些索引被实际使用 294 2.4.3.2.5 表之间的引用 295 2.4.3.2.6 每张表有多少行被优化器查询 296 297 2.4.3.3 怎么玩 298 select * from tbl_emp; 299 explain select * from tbl_emp; 300 ①Explain + sql语句 301 ②执行计划包含信息 ☆ 302 表头:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra 303 304 2.4.3.4 各字段解释 305 2.4.3.4.1 id 306 ①select查询的序列号,包含一组数字表示查询中执行select子句或操作表达表的顺序 307 ②三种情况 308 一、id相同,执行顺序由上至下 309 explain select t2.* 310 from t1,t2,t3 311 where t1.id = t2.id and t1.id =t3.id 312 and t1.other_column = ''; 313 二、id不通,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行 314 explain select t2.* 315 from t2 316 where id =(select id 317 from t1 318 where id = (select t3.id 319 from t3 320 where t3.other_column = '' 321 ) 322 ) 323 324 三、id相同不同,同时存在, 325 id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行 衍生=DERIVED 326 explain select t2.* from ( 327 select t3.id 328 from t3 329 where t3.other_column = '') s1,t2 330 where s1.id = t2.id; 331 332 2.4.3.4.2 select_type 333 ①有哪些 334 simple、primary、subquery、derived、union、union result 335 ②查询的类型,主要是用于区别普通查询、联合查询、子查询等复杂查询 336 一、simple 337 简单的select查询,查询中不包含子查询或者union。 338 二、primary 339 查询中若包含任何复杂的子部分,最外层查询则被标记。 340 三、subquery 341 在select或where列表中包含了子查询。 342 四、derived 343 在from列表中包含子查询被标记为derived(衍生)mysql会递归执行这些子查询,把结果放在临时表里。 344 五、union 345 若第二个select出现在union之后,则被标记为union; 346 若union包含在from子句的子查询中,外层select将被标记为:derived 347 六、union result 从union表获取结果的select 348 349 2.4.3.4.3 table 350 显示这一行的数据是关于哪张表的 351 352 2.4.3.4.4 type 353 all、index、range、ref、eq_ref、const,system、null 354 访问类型排列 355 type显示的访问类型,是较为重要的一个指标,结果值从最好到最坏一次是: 356 system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL 357 显示查询使用了何种类型,从最好到最差一次是: 358 system>const>eq_ref>ref>range>index>ALL,一般来说,得保证查询至少达到range级别,最好能达到ref。 359 一、system 360 表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也可以忽略不计。 361 二、const 362 表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快 363 如将逐渐置于where列表中,Mysql就能将该查询转换为一个常量 364 例子:explain select * from (select * from t1 where id =1) d1; 365 1 primary <derived2> system 366 2 derived t1 const 367 三、eq_ref 368 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描 369 例子:explain select * from t1,t2 where t1.id =t2.id 370 1 t2 simple all 371 1 t1 simple eq_ref 372 四、ref 373 非唯一性索引扫描,返回匹配某个单独值的所有行。 374 本质上也是一个索引访问,它返回所有匹配某个单值的行,然而, 375 它可能找到过个符合条件的行,所以他应该属于查找和扫描的混合体 376 例子:create index idx_col1_col2 on t1(col1,col2); 377 select count(distinct col1) from t1; 378 explain select * from t1 where col1 = 'ac'; 379 五、range 380 只检索给定范围的行,使用每一个索引来选择行,key列显示使用了哪个索引 381 一般就是在你的where语句中出现了between、<、>、in等的查询 382 这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点而结束语另一点,不用扫描全部索引。 383 例子:explain select * from t1 where id between 30 and 60; 384 1 simple t1 range 385 explain select *from t1 where id in (1,2,6); 386 1 simple t1 range 387 六、index 388 full index scan,index与all区别为index类型只遍历索引树,这通常比all快,因为索引文件通常比数据文件小。 389 (也就是虽然all和index都是读全表,但index是从索引中读取数据的,而all是从硬盘中读取的) 390 explain select id from t1; 391 1 simple t1 index 392 七、all 393 full table scan,将遍历全表以找到匹配到的行 394 备注:一般来说,保证查询至少达到range级别,最好能达到ref 395 396 2.4.3.4.5 possible_keys 397 显示可能应用在这张表中的索引:一个或多个 398 查询涉及到的字段上若存在索引,则将该索引列出,但不一定被查询实际使用 399 400 2.4.3.4.6 key 401 实际使用的索引,如果为null,则没有使用索引 402 查询中若使用了覆盖索引,则该索引进程出现在key列表中 403 例子:explain select col1,col2 from t1 404 1 simple t1 index null idx_col1_col2 405 406 2.4.3.4.7 key_len 407 表示索引中国使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好 408 key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出来的 409 410 2.4.3.4.8 ref 411 显示索引的哪一个列被使用了,如果可能的话是一个常数。哪些列或常量被用于查找索引列上的值 412 例子:explain select * from t1,t2 where t1.col1 = t2.col1 and t1.col2 = 'ac'; 413 1 t2 all null null null null 414 1 t1 ref idx_col1_col2 idx_col1_col2 26 shared.t2.col1,const 415 416 2.4.3.4.9 rows 417 根据表统计信息及索引的选用情况,大致估算出找得到所需的记录所需要读取的行数 418 例子: 419 2.4.3.4.10 Extra 420 包含不适合在其他列中显示但十分重要的额外信息 421 一、Using filesort 422 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。 msyql中无法利用索引完成的排序操作称为“文件排序”。 423 例子:explain select col1 from t1 where col1 = 'ac' order by col3\G #中间2没有了 424 1 simple t1 ref idx_col1_col2_col3 idx_col1_col2_col3 13 const 142 Using where;Using index;Using filesort 425 例子:explain select col1 from t1 where col1 = 'ac' order by col2,col3\G #性能高 426 1 simple t1 ref idx_col1_col2_col3 idx_col1_col2_col3 13 const 142 Using where;Using index 427 二、Using temporary 428 使用临时表保存了中间结果,mysql在对外查询结果排序时使用临时表,常见于排序order by和分组查询group by。 429 例子:explain select col1 from t1 where col1 in ('ac','ab','aa') group by col2\G 430 id simple t1 range idx_col1_col2 idx_col1_col2 13 null 569 Using where;Using index;Using temporary;Using filesort 431 explain select col1 from t1 where col1 in ('ac','ab') group by col1,col2\G 432 id simple t1 range idx_col1_col2_col3 idx_col1_col2_col3 26 null 4 Using where;Using index for group by 433 三、Using index 434 表示相应的select操作中使用了覆盖索引(Cover Index),避免访问了表的数据行,效率不错! 435 如果同时出现useing where,表明索引被用来执行索引键值的查找; 436 如果没有同时出现using where表明索引用来读取该数据而非执行查找动作; 437 例子:explain select col2 form t1 where col1='ab'; 438 1 ,,, idx_col1_col2 idx_col1_col2 13 const 143 Using where;using index; 439 explain select col1,col2 form t1 440 1 simple t1 index null idx_col1_col2 398 null 682 usring index 441 覆盖索引(Covering Index) 442 理解方式一:就是select的数据列只从索引中就能够获取得,不必读取数据行,Mysql可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件, 443 换句话说查询列要被所建的索引覆盖 444 理解方式二:索引是高效查找到行的一个方法,但是一般数据库也能使用索引找到一列的数据,因此它 不必读取整个行,毕竟索引叶子节点存储了他们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足 445 查询结果数据就叫覆盖索引 446 注意: 447 如果要使用覆盖索引,一定注意select列表中只取出需要的列,不可select *。 448 因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降。 449 四、Using where 450 表明使用了where过滤 451 五、Using join buffer 452 使用了连接缓存 453 六、impossible where 454 where子句的值总是fale,不能用来获取任何元组 455 例子:explain select * from staffs where name = 'july' and name = 'z3'; 456 1 simple null null null null null null null impossible where 457 七、select tables optimized away 458 在没有GROUP BY子句的情况下,基于索引优化MIN/MAX操作或者 459 对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算 460 查询执行计划生成的阶段即完成优化。 461 八、distinct 462 优化distinct操作,在找到第一匹配的元组后即停止找同样值的操作 463 464 465 2.4.3.5 热身case 466 例子:explain select d1.name,(select id from t3) d2 467 from (select id,name form t1 where t1 where other_column = '') d1 468 union 469 (select name,id from t2); 470 1 primary <derived3> system null null null null 1 471 3 derived t1 all null null null null 1 Using where 472 2 subquery t3 index null primary 4 null 1 using where 473 4 union t2 all null null null null 1 474 null nuion result <uion1,4> all null null null null null 475 优化sql语句 476 第一行(执行顺序4):id列为1,表示是union里的第一个select,select_type列的primary表是该查询为外层查询,table列被标记为<derived3>, 477 表示结果来自一个衍生表,其中derived3中3代表该查询衍生自第三个select查询,即id为3的select。【select d1.name......】 478 第二行(执行顺序2):id为3,是整个查询中第三个select的一部分,因查询包含在from中,所以为derived。【select id.name from t1 where other_column=''】 479 第三行(执行顺序3):select列表中的子查询select_type为subquery,为整个查询中的第二个select。【select id from t3】 480 第四行(执行顺讯1):select_type为union,说明第四个select是union里的第二个select,最先执行【select name.id from 12】 481 第五行(执行顺序5):代表从union的临时表中读取行的阶段,table列的<union1,4>表示用第一个和第四个select的结果进行union操作。【两个结果union操作】 482 2.5索引优化 483 2.5.1 索引分析 484 2.5.1.1 单表 485 一、建表sql 486 CREATE TALBE IF NOT EXISTS `article`( 487 `id` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 488 `author_id` INT(10) UNSIGNED NOT NULL, 489 `category_id` INT(10) UNSIGNED NOT NULL, 490 `views` INT(10) UNSIGNED NOT NULL, 491 `comments` INT(10) UNSIGNED NOT NULL, 492 `title` VARCHAR(255) NOT NULL, 493 `content` TEXT NOT NULL 494 ); 495 INSERT INTO `article`(`author_id`,`category_id`,`views`,`comments`,`title`,`content`)VALUES 496 (1,1,1,1,'1','1'), 497 (2,2,2,2,'2','2'), 498 (3,3,3,3,'3','3'); 499 二、案例 500 #查询category_id为1且comments大于1的情况下,views最多的article_id 501 EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments>1 ORDER BY views DESC LIMIT 1; 502 1 simple article all null null null null 3 Using where;Using filesort 503 show index from article; 504 #结论:很显然,type是all,即最坏的情况,Extra里还出现了Using filesort,也是最坏的情况,优化是必须的。 505 #开始优化: 506 507 #1.1 新建索引+删除索引 508 ##ALTER TABLE 'article' ADD INDEX idx_article_ccv(`category_id`,`comments`,`views`); 509 create index idx_article_ccv on article(category_id,comments,views); 510 show index from article; 511 EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments>1 ORDER BY views DESC LIMIT 1; 512 1 simple article range idx_article_ccv idx_article_ccv 8 null 1 Using where;Using filesort 513 调整sql语句 514 EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments=1 ORDER BY views DESC LIMIT 1;#范围会导致索引失效,同样一个索引条件不一样,查询结果和性能是不一样的,以后跟产品经理提需求尽量提等于, 515 #产品经理关注产品没关不会关注字段,但是作为研发和产品经理碰需求,尽量引导他,比如这个字段不能为空,不是我们做不出,是影响性能 516 1 simple article ref idx_article_ccv idx_article_ccv 8 const,const 1 Using where;Using filesort 517 DROP INDEX idx_article_ccv on article 518 #1.2 第2次EXPLAIN 519 EXPLAIN SELECT id,author_id FROM `article` WHERE category_id = 1 AND comments>1 ORDER BY VIEWS DESC LIMIT 1; 520 EXPLAIN SELECT id,author_id FROM `article` WHERE category_id = 1 AND comments=3 ORDER BY VIEWS DESC LIMIT 1; 521 #结论: 522 #type 变成了range,这是可以忍受的。但是extra里使用Using filesort仍是无法忍受的。 523 #但是我们已经建立了索引,为啥没用呢? 524 #这是因为按照BTree索引的工作原理 525 #先排序category_id, 526 #如果遇到相同的category_id则再排序comments,如果遇到相同的comments则再排序views。 527 #当comments字段在联合索引里处于中间位置时, 528 #因comments>1条件是一个范围值(所谓range), 529 #MySQL无法利用索引再对后面的views部分进行检索,即range类型查询字段后面的索引无效。 530 531 #1.3删除第一次建立的索引 532 DROP INDEX idx_article_ccv ON article 533 534 #1.4第2次删除新建索引 535 #ALTER TABLE `article` ADD INDEX idx_article_cv(`category`,`views`); 536 create index idx_article_cv on article(category_id,views); 537 EXPLAIN SELECT id,author_id FROM article WHERE category_id = 1 AND comments>1 ORDER BY views DESC LIMIT 1; 538 1 simple article ref idx_article_cv 4 const 2 Using where 539 540 2.5.1.2 两表 541 一、建表 542 CREATE TABLE IF NOT EXISTS `class`( 543 `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 544 `card` INT(10) UNSIGNED NOT NULL, 545 PRIMARY KEY(`id`) 546 ); 547 CREATE TALBE IF NOT EXISTS `book`( 548 `bookid` INT(10) UNSIGNED NOT NULLL AUTO_INCREMENT, 549 `card` INT(10) UNSIGNED NOT NULL, 550 PRIMARY KEY(`bookid`) 551 ) 552 553 INSERT INTO class(card) VALUES(FLOOR(1+(RAND()+20))); 554 INSERT INTO class(card) VALUES(FLOOR(1+(RAND()+20))); 555 INSERT INTO class(card) VALUES(FLOOR(1+(RAND()+20))); 556 INSERT INTO class(card) VALUES(FLOOR(1+(RAND()+20))); 557 INSERT INTO class(card) VALUES(FLOOR(1+(RAND()+20))); 558 ...20 559 INSERT INTO book(card) VALUES(FLOOR(1+(RAND()+20))); 560 INSERT INTO book(card) VALUES(FLOOR(1+(RAND()+20))); 561 INSERT INTO book(card) VALUES(FLOOR(1+(RAND()+20))); 562 563 select * from book inner join class on book.card = class.card; 564 二、案例 565 #下面开始explain分析 566 EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; 567 #结论:type 有all 568 569 #添加索引优化 570 ALTER TABLE `book` ADD INDEX Y(`card`); 571 572 #第2次explain 573 EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; 574 #可以看到第二行的type变为了ref,rows也变为了优化比较明显。 575 #这是由左连接的特性决定的。LEFT JOIN 条件用于确定如何从右表搜索,左边一定都有, 576 #所以右边是关键点,一定要建立索引。 577 578 #删除旧索引+新建+第3次explain 579 DROP INDEX Y ON book; 580 581 2.5.1.3 三表 582 一、建表sql 583 二、案例 584 2.5.2 索引失效(应该避免) 585 2.5.3 一般性建议 586 3、查询截取分析 587 3.1查询优化 588 3.2慢查询日志 589 3.3批量数据脚本 590 3.4Show Profile 591 3.5全局查询日志 592 4、Mysql锁机制 593 4.1概述 594 4.2表锁 595 4.3行锁 596 4.4页锁 597 4.4小结 598 开锁、加锁速度、死锁、粒度、并发性能只能就具体的应用特点来说那种更适合 599 5、主从复制 600 复制的基本原则 601 复制的最大问题 602 一主一从常见配置
标签:高级,查询,索引,Mysql,null,where,id,select 来源: https://www.cnblogs.com/landerhu/p/12512896.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。