MySQL 数据库--SQL语句优化
explain查询和分析sql
开发中,为满足一业务功能,使用mysql书写sql时,一条sql往往有多种写法,那么我们就需要选择执行效率比较高的sql。
因此要比较分析sql的执行过程,且同一条sql我们要比较选择使用最优索引。
通过explain命令可以得到。
先整体了解下SQL查询的基本执行过程:
)应用通过MySQL API把查询命令发送给MySQL服务器,然后被解析 )检查权限、MySQL optimizer进行优化,经过解析和优化后的查询命令被编译为CPU可运行的二进制形式的查询计划(query
plan),并可以被缓存 )如果存在索引,那么先扫描索引,如果数据被索引覆盖,那么不需要额外的查找,如果不是,根据索引查找和读取对应的记录 )如果有关联查询,查询次序是扫描第一张表找到满足条件的记录,按照第一张表和第二张表的关联键值,扫描第二张表查找满足条件的记录,按此顺序循环
)输出查询结果,并记录binary logs
Explain返回信息:
通过explain可以得到如下结论:
①使用索引比未使用索引,扫描的行数更少查询速度更快;
②在查询语句中使用LIKE关键字进行查询时,如果匹配字符串的第一个字符为“%”时,索引不会被使用。如果“%”不是在第一个位置,索引就会被使用。
③使用多列索引时,只有查询条件中使用了该索引中的第一个索引字段时,索引才会被使用。
注:create index index_age_sex on user(age,sex); age为第一个索引;
④查询语句只有OR关键字时,如果OR前后的两个条件列都是索引时,查询中将使用索引。只要OR前后有一个条件的列不是索引,那么查询中将不使用索引。
注: 1:where 语句里面如果带有or条件, myisam表能用到索引,innodb不行;2:必须所有的or条件都必须是独立索引;
⑤经过普通运算或函数运算后的索引字段不能使用索引。
但是,经过函数运算字段的字段要使用可以使用函数索引,这种需求建议与DBA沟通。
以上结论来自如下测试:
|
user表: 独立索引:id、name 联合索引:age && sex |
user_noindex表: 无任何索引列; |
|
CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(30) NOT NULL, `age` int(11) NOT NULL, `sex` tinyint(4) NOT NULL, `isDeleted` tinyint(4) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id_unidx` (`id`) USING BTREE, UNIQUE KEY `name_unidx` (`name`) USING BTREE, KEY `index_age_sex` (`age`,`sex`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
CREATE TABLE `user_noindex` ( `id` int(11) NOT NULL, `name` varchar(30) NOT NULL, `age` int(11) DEFAULT NULL, `sex` tinyint(4) DEFAULT NULL, `isDeleted` tinyint(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
【1】索引对查询的影响-----加索引和不加索引的对比-----使用索引扫描的更少查询更快
语句1:explain SELECT * FROM `user` where name = 'name6';
语句2:explain SELECT * FROM `user_noindex` where name = 'name6';
| 结果集 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 语句1 | 1 | SIMPLE | user | const | name_unidx | name_unidx | 32 | const | 1 | null |
| 语句2 | 1 | SIMPLE | user_noindex | ALL | null | null | null | null | 10 | Using where |
【2】索引对查询的影响-----加索引----使用和未使用索引的对比-----在查询语句中使用LIKE关键字进行查询时,如果匹配字符串的第一个字符为“%”时,索引不会被使用。如果“%”不是在第一个位置,索引就会被使用。
语句1:explain SELECT * FROM `user` where name like '%name6';
语句2:explain SELECT * FROM `user` where name like '%name6%';
语句3:explain SELECT * FROM `user` where name like 'name6%';
| 结果集 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 语句1 | 1 | SIMPLE | user | ALL | null | null | null | null | 10 | Using where |
| 语句2 | 1 | SIMPLE | user | ALL | null | null | null | null | 10 | Using where |
| 语句3 | 1 | SIMPLE | user | range | name_unidx | name_unidx | 32 | const | 1 | null |
【3】索引对查询的影响-----加索引----使用和未使用索引的对比-----多列索引是在表的多个字段创建一个索引。只有查询条件中使用了这个字段中的第一个字段时,索引才会被使用。
语句1:explain SELECT * FROM `user` where age = '19';
语句2:explain SELECT * FROM `user` where sex = '1';
语句3:explain SELECT * FROM `user` where sex = '1' and age = '19';
| 结果集 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 语句1 | 1 | SIMPLE | user | ref | index_age_sex | index_age_sex | 4 | const | 1 | null |
| 语句2 | 1 | SIMPLE | user | ALL | null | null | null | null | 10 | Using where |
| 语句3 | 1 | SIMPLE | user | ref | index_age_sex | index_age_sex | 5 | const,const | 1 | null |
【4】索引对查询的影响-----加索引----使用和未使用索引的对比-----查询语句只有OR关键字时,如果OR前后的两个条件的列都是索引时,查询中将使用索引。如果OR前后有一个条件的列不是索引,那么查询中将不使用索引。
语句1:explain SELECT * FROM `user` where (age = '19' OR isDeleted = '0');
语句2:explain SELECT * FROM `user` where (sex = '1' OR age = '19'); -- 联合索引
语句3:explain SELECT * FROM `user` where (name = 'name1' OR id = '1'); -- 独立索引
-- alter table user engine = innodb;
| 结果集 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 语句1 | 1 | SIMPLE | user | ALL | index_age_sex | null | null | null | 10 | Using where |
| 语句2 | 1 | SIMPLE | user | ALL | index_age_sex | null | null | null | 10 | Using where |
| 语句3 | 1 | SIMPLE | user | ref | PRIMARY,id_unidx,name_unidx | index_age_sex | null | null | 10 | Using where |
-- alter table user engine = myisam;
| 结果集 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 语句1 | 1 | SIMPLE | user | ALL | index_age_sex | null | null | null | 10 | Using where |
| 语句2 | 1 | SIMPLE | user | ALL | index_age_sex | null | null | null | 10 | Using where |
| 语句3 | 1 | SIMPLE | user | index_merge | PRIMARY, id_unidx, name_unidx |
name_unidx, PRIMARY |
32,4 | null | 2 | Using union (name_unidx,PRIMARY); Using where |
很多查询中需要使用子查询。子查询可以使查询语句很灵活,但子查询的执行效率不高。子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句在临时表中查询记录。查询完毕后,MySQL需要撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。在MySQL中可以使用连接查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快。
limit查询的优化
优化limit查询 .
limit常用于分页处理,时常会伴随order by从句使用,因此大多时候会使用Filesorts这样会造成大量的io问题
select film_id,description from sakila.film order by title limit 50,5; #title列不是索引也不是主键
优化步骤1:使用有索引的列或主键进行order by操作
select film_id ,description from sakila.film order by film_id limit 50,5; #把索引film_id进行order by操作,但仍然扫描了55行。
优化步骤2:记录上次返回的主键,在下次查询时用 主键过滤(避免了数据量大时扫描过多的记录)
select film_id ,description from sakila.film where film_id >55 and film_id<=60 order by film_id limit 1,5 #知道查询的范围为55~60,否则会扫描60行,使用主键过滤where film_id >55 and film_id<=60后只扫描了5行,避免了数据量大时扫描过多的记录。
优化limit查询2。使用这种方式要求主键是按顺序排序,如果中间有断层,则返回的数据行数不符,例如在film_id 55~60中少了一行,则排序是要排5行,则就会出错。
MySQL 数据库--SQL语句优化的更多相关文章
- 千万级大数据的Mysql数据库SQL语句优化
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- php面试专题---MySQL常用SQL语句优化
php面试专题---MySQL常用SQL语句优化 一.总结 一句话总结: 原理,万变不离其宗:其实SQL语句优化的过程中,无非就是对mysql的执行计划理解,以及B+树索引的理解,其实只要我们理解执行 ...
- MySQL 数据库SQL语句——高阶版本2
MySQL 数据库SQL语句--高阶版本2 实验准备 数据库表配置: mysql -uroot -p show databases; create database train_ticket; use ...
- mysql的sql语句优化方法面试题总结
mysql的sql语句优化方法面试题总结 不要写一些没有意义的查询,如需要生成一个空表结构: select col1,col2 into #t from t where 1=0 这类代码不会返回任何结 ...
- MySQL 数据库SQL语句——高阶版本1
MySQL 数据库SQL语句--高阶版本 实验准备,数据表配置 mysql -uroot -p show databases; create database train_ticket; use tr ...
- MySQL数据库sql语句的一些简单优化
1.查询条件的先后顺序 有多个查询条件时,要把效率高能更精确筛选记录的条件放在后边.因为MySQL解析sql语句是从后往前的(不知是否准确). 例: select a.*,b.* from UsrIn ...
- MySQL数据库SQL语句基本操作
一.用户管理: 创建用户: create user '用户名'@'IP地址' identified by '密码'; 删除用户: drop user '用户名'@'IP地址'; 修改用户: renam ...
- MySQL常用SQL语句优化
推荐阅读这篇博文,索引说的非常详细到位:http://blog.linezing.com/?p=798#nav-3-2 在数据库日常维护中,最常做的事情就是SQL语句优化,因为这个才是影响性能的最主要 ...
- MySQL之SQL语句优化
语句优化 即优化器利用自身的优化器来对我们写的SQL进行优化,然后再将其放入InnoDB引擎中执行. 条件简化 移除不必要的括号 select * from x where ((a = 5)); 上面 ...
随机推荐
- Spring框架的设计理念
它这种设计策略完全类似于Java实现OOP的设计理念,当然Java本身的设计要比Spring复杂太多太多,但是它们都是构建一个数据结构,然后根据这个数据结构设计它的生存环境,并让它在这个环境中按照一定 ...
- SOAP1.1 and SOAP1.2
在用cxf 做webservice客户端的时候碰到的: javax.xml.ws.soap.SOAPFaultException: A SOAP 1.2 message is not valid wh ...
- iOS 性能优化套路
*** 一级套路 *** 使用ARC管理内存- 防止内存泄露- 保证释放掉不再需要的内存,提高性能 在正确的地方使用 reuseIdentifier平时接触的需要考虑重用的视图有UICollect ...
- 第10天:apply和call、bind、函数作为参数、返回值使用、闭包、递归的样例
apply和call apply和call都可以改变this的指向 函数的调用,改变this的指向 函数名字.apply(对象,[参数1,参数2,.....]) 方法名字.apply(对象,[参数1, ...
- ASP.NET页面支持的指令
页面的处理指令 页面指令的处理用于配置执行该页面的运行时环境.在ASP.NET中,指令可以位于页面的任何位置,但良好且常见的习惯是将其置于文件的开始部分.除此,页面指令的名称是不区分大小写的,且指令的 ...
- 【SSH网上商城项目实战17】购物车基本功能的实现
转自:https://blog.csdn.net/eson_15/article/details/51418350 上一节我们将商品的详细页面做完了,并使用了Hibernate的二级缓存加载详细页面来 ...
- JavaWeb中监听器
一.事件源:三大域! ServletContext 生命周期监听:ServletContextListener,它有两个方法,一个在创建时调用,一个在销毁时调用: void contextIniti ...
- java 简单计算器
package com.direct.demo; import java.text.DecimalFormat; import java.util.Scanner; public class Calc ...
- data-id 和 id 的区别
作者:Zeropoint零点 来源:CSDN 原文:https://blog.csdn.net/qq_41648132/article/details/80364335 版权声明:本文为Zeropoi ...
- select实现三级联动
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...