1.explain分析
explian引用
索引基数
show indexes from table_name;
主键索引具有最好的基数

测试时

不走缓存
SELECT SQL_NO_CACHE id from test_null;

2.更好的索引类型
索引列尽可能的为not null ,避免在可空的列索引上进行二次扫描
要尽量避免 NULL ,关于索引列为Null的是否走索引,见测试 索引列的值为null查询时走索引的情况
3.使用unique index
与常规索引比不需要进行索引范围扫描
4.使用primary key
主键是uniquekey的一种特殊形式 。在innodb中,一个uniquekey是一个聚集索引(即对磁盘上数据排列的索引),当数据按照主键的次序进行检索时会极大改进性能
5.索引太多是有害的
例如,如果possible_keys 列表中有超过3个的索引,mysql优化器有太多信息而无法确定最好使用哪个索引,也就意味着有些是低效或者无用的索引
6.索引列使用最小可能的数据类型
比如在一个varchar(100)甚至更大的列上建立索引,一种改进方法是建立一个额外的列,并在包含较大的varchar(100)列的md5值的额外varchar(32)列上创建索引。
更好的方法是使用bigint来存储md5值的数字表示,数字索引更加高效
CONV(N,from_base,to_base)

mysql> select conv('a',16,10);
+-----------------+
| conv('a',16,10) |
+-----------------+
| 10 |
+-----------------+
mysql> select conv(substr(md5('abc'),1,16),16,10);
+-------------------------------------+
| conv(substr(md5('abc'),1,16),16,10) |
+-------------------------------------+
| 10376663631224000432 |
+-------------------------------------+

7.建立索引时
如果使用到多个列,定义多列索引
哪列的唯一性更高(基数大 show indexes from table_name),哪列优先放在多列索引的前面
覆盖索引是理性的索引 (explain 里extra的信息时using index)

覆盖索引包括所有需要的列,但是不需要读取单独的数据页,实际意味着不需要读取数据存储,只利用索引数据就可以检索到实际想要的查询的数据
在myisam表里,意味着只要读入索引就可以得到问题的记录,在innodb中 索引和数据是位于同一个文件中的,但仍然会高效些,因为只需要读入索引
优化部分索引的性能

select type from tb where sid=1

建立(sid,type)的索引 就是覆盖索引,比单独在sid,type上建索引要快

与其在长字符的列上定义索引,还不如只在左边的一小部分上建立索引

8.一些常见的不使用索引的情况
开始字符是通配符是,或者 在索引列上使用标量函数
like "%123",upper()

字符串类型的查询不加引号
9.覆盖索引的左前缀原则

10.更详细的分析
set profiling=1;
select * from table;
show profile;
show profile source ;

mysql> select * from test_null where mark like 'aaa9999%';
+------+---------+
| id | mark |
+------+---------+
| 9999 | aaa9999 |
+------+---------+
1 row in set mysql> show profile;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 5.5E-5 |
| checking permissions | 1.1E-5 |
| Opening tables | 2E-5 |
| init | 2.4E-5 |
| System lock | 7E-6 |
| optimizing | 8E-6 |
| statistics | 1.4E-5 |
| preparing | 7E-6 |
| executing | 2E-6 |
| Sending data | 0.006271 |
| end | 5.7E-5 |
| query end | 3.6E-5 |
| closing tables | 5.1E-5 |
| freeing items | 0.000348 |
| cleaning up | 0.00011 |
+----------------------+----------+
mysql> show profile source;
+----------------------+----------+-----------------------+----------------------+-------------+
| Status | Duration | Source_function | Source_file | Source_line |
+----------------------+----------+-----------------------+----------------------+-------------+
| starting | 5.5E-5 | NULL | NULL | NULL |
| checking permissions | 1.1E-5 | check_access | sql_authorization.cc | 835 |
| Opening tables | 2E-5 | open_tables | sql_base.cc | 5648 |
| init | 2.4E-5 | handle_query | sql_select.cc | 121 |
| System lock | 7E-6 | mysql_lock_tables | lock.cc | 321 |
| optimizing | 8E-6 | JOIN::optimize | sql_optimizer.cc | 151 |
| statistics | 1.4E-5 | JOIN::optimize | sql_optimizer.cc | 367 |
| preparing | 7E-6 | JOIN::optimize | sql_optimizer.cc | 475 |
| executing | 2E-6 | JOIN::exec | sql_executor.cc | 119 |
| Sending data | 0.006271 | JOIN::exec | sql_executor.cc | 195 |
| end | 5.7E-5 | handle_query | sql_select.cc | 199 |
| query end | 3.6E-5 | mysql_execute_command | sql_parse.cc | 4952 |
| closing tables | 5.1E-5 | mysql_execute_command | sql_parse.cc | 5004 |
| freeing items | 0.000348 | mysql_parse | sql_parse.cc | 5578 |
| cleaning up | 0.00011 | dispatch_command | sql_parse.cc | 1864 |
+----------------------+----------+-----------------------+----------------------+-------------+
mysql> set profiling=1;
Query OK, 0 rows affected mysql> select * from a;
+----+-----+-------+
| id | uid | phone |
+----+-----+-------+
| 1 | 1 | 22 |
| 2 | 2 | 33 |
| 3 | 3 | 33 |
| 4 | 4 | 22 |
| 5 | 5 | 22 |
+----+-----+-------+
5 rows in set mysql> select * from b;
+-------+
| phone |
+-------+
| 1111 |
| 2222 |
| 3333 |
| 4444 |
+-------+
4 rows in set mysql> show profiles;
+----------+------------+-----------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------+
| 1 | 0.00025225 | select * from a |
| 2 | 0.0009805 | select * from b |
+----------+------------+-----------------+
2 rows in set mysql> show profile for query 2;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000106 |
| checking permissions | 1.4E-5 |
| Opening tables | 3.3E-5 |
| init | 3E-5 |
| System lock | 2E-5 |
| optimizing | 0.000259 |
| statistics | 4.5E-5 |
| preparing | 2.5E-5 |
| executing | 4E-6 |
| Sending data | 0.000358 |
| end | 7E-6 |
| query end | 6E-6 |
| closing tables | 8E-6 |
| freeing items | 5.4E-5 |
| cleaning up | 1.4E-5 |
+----------------------+----------+
15 rows in set

优化update
换成select使用explain

优化delete

mysql> select * from parent;
+----+------+
| id | name |
+----+------+
| 1 | pa |
| 2 | pb |
| 3 | pc |
| 4 | pd |
+----+------+
4 rows in set mysql> select * from child;
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 1 | 4 |
| 1 | 5 |
| 2 | 6 |
| 0 | 7 |
| 5 | 8 |
| 6 | 9 |
| 5 | 10 |
+-----------+----------+

删除child中parent_id不在parent表的记录
一般的写法是
delete from child where parent_id not in(select id from parent);
更加高效的是使用连接查询
通过以下来验证

set profiling=1;
select * from child where parent_id not in(select id from parent);

select child.* from child left join parent on child.parent_id=parent.id where parent.id is null;

select query_id,count(*) as '#ops' ,sum(duration) from information_schema.profiling group by query_id;
select * from information_schema.profiling ;

演示结果
mysql> set profiling=1;
Query OK, 0 rows affected mysql> select * from child where parent_id not in(select id from parent);
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
| 0 | 7 |
| 5 | 8 |
| 6 | 9 |
| 5 | 10 |
+-----------+----------+
4 rows in set mysql> select child.* from child left join parent on child.parent_id=parent.id where parent.id is null;
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
| 0 | 7 |
| 5 | 8 |
| 6 | 9 |
| 5 | 10 |
+-----------+----------+
4 rows in set mysql> select query_id,count(*) as '#ops' ,sum(duration) from information_schema.profiling group by query_id;
+----------+------+---------------+
| query_id | #ops | sum(duration) |
+----------+------+---------------+
| 1 | 23 | 0.000749 |
| 2 | 16 | 0.000388 |
+----------+------+---------------+

优化器显示第二个用了更少的操作
优化Insert,同一表的多条类似的多个insert改写成1条减少数据库的网络往返
例外一个好处是mysql只需为insert语句产生一次执行计划,可以在多个值上利用同一个执行计划
当批量插入时,如果单个插入失败,多个value子句说明的记录都无法插入成功

优化insert ...on duplicate key update
replace在内部是使用delete和insert来实现的,因而其效率并不高
使用insert ...on duplicate key update
如果存在同样主键值的记录,而其它列与现在存指定的记录有所不同,就更新该记录,如果记录不存在就插入该记录,如果记录存在而且没有任何值发生改变
就不做任何操作,优于replace

mysql> desc a;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| sid | int(11) | YES | | NULL | |
| type | char(10) | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
mysql> select * from a;
+----+-----+------+
| id | sid | type |
+----+-----+------+
| 1 | 11 | aa |
| 2 | 1 | b |
| 3 | 2 | c |
| 4 | 3 | d |
+----+-----+------+
mysql> insert into a(`id`,`type`) values(1,'a1');
1062 - Duplicate entry '' for key 'PRIMARY'
mysql> insert into a(`id`,`type`) values(1,'a1') on duplicate key update type='a1';
Query OK, 2 rows affected
注意改变的是2行
mysql> insert into a(`id`,`type`) values(5,'a5') on duplicate key update type='a5';
Query OK, 1 row affected
mysql> select * from a;
+----+------+------+
| id | sid | type |
+----+------+------+
| 1 | 11 | a1 |
| 2 | 1 | b |
| 3 | 2 | c |
| 4 | 3 | d |
| 5 | NULL | a5 |
+----+------+------+

11.优化group by  在sakila

explain select actor.first_name,actor.last_name,count(*) from film_actor
INNER JOIN actor USING(actor_id) GROUP BY film_actor.actor_id; explain SELECT actor.first_name,actor.last_name,c.cnt from actor INNER JOIN
(SELECT actor_id ,count(actor_id) as cnt from film_actor GROUP BY actor_id)
as c USING(actor_id);

小表 全表扫描效率更高
主键可以与外键构成参照完整性约束,防止数据不一致,唯一索引不行
覆盖索引

复合索引前缀规则
like %不能在前面
column is null可以使用索引
如果mysql估计使用索引比全表扫描慢,会放弃使用索引 (比如100条数据,查 where id >1 and id <100)
如果or前的的条件的列有索引,后面的没有,索引都不会用到 (where a=1 or b=2 a有索引,b没有,则都不会用到索引)

列类型是字符串类型,查询时一定要给值加引号,否则索引会失效 (name varchar(10)  存个100  where name=100 会索引失效)

关联更新

tb1 (id,sex,par,c1,c2)
tb2 (id ,age,c1,c2) update A,B set tb1.c1=tb2.c1,tb1.c2=tb2.c2 where tb1.id=tb2.id and tb2.age>50 update tb1 inner join tb2 on tb1.id=tb2.id
set tb1.c1=tb2.c1,tb1.c2=tb2.c2
where tb2.age>50

show status
返回一些计数器,show global status查看服务器级别的所有计数
show processlist
观察是否有大量的线程处于不正常状态

mysql> show processlist;
+----+------+-----------------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------+------+---------+------+----------+------------------+
| 2 | root | localhost:50043 | NULL | Sleep | 1019 | | NULL |
| 3 | root | localhost:50044 | yii2 | Sleep | 1019 | | NULL |
| 8 | root | localhost:50317 | yii2 | Query | 0 | starting | show processlist |
+----+------+-----------------+------+---------+------+----------+------------------+

其它需要注意的小细节

范式修改
优化长难的查询语句

Mysql内部每秒可扫描内存中上百万行数据,相比之下,相应数据给客户端就要慢得多
使用尽可能少的查询
有时将一个大查询分解为多个小的查询时有必要的(方便缓存)

切分查询
将一个大查询分解为多个小的相同查询
一次性删除10000万的数据比一次删除1万暂停一会的方案更加损耗服务器开销

分解关联查询
将一条关联语句分解成多条sql语句来执行
让缓存效率更高
执行单个查询可以减少锁的竞争
在应用层做关联查询可以更容易对数据库进行拆分

优化特定类型查询语句
count(*) 会忽略所有列,直接统计所有列数,因此不要使用count(列名)
在myisam中,没有任何where条件的count(*)非常快
有where的话就不一定比其它的引擎快
可以使用explain查询近似值,用近似值代替count(*)
增加汇总表,缓存

优化关联查询
确定on或者using子句列上有索引
确保group by 和order by中只有一个表中的列,mysql才可能使用到索引
使用标识列更快

优化子查询
使用关联查询替代

优化group by和distinct

如果不需要order by进行group by时使用order by null,mysql不再进行文件排序
with rollup超级聚合,可以挪到应用程序处理
优化limit分页(加条件 比如 id>上次最后一个id)

优化union
union all效率高于union

mysql常见的优化需要注意的点的更多相关文章

  1. mysql常见的优化方法

    1.选取适当的字段属性.例如,在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任 ...

  2. Mysql常见的优化策略

    数据库设计方面优化 1.数据库设计符合第三范式,为了查询方便可以有一定的数据冗余.2.选择数据类型优先级 int > date,time > enum,char>varchar &g ...

  3. (1.10)SQL优化——mysql 常见SQL优化

    (1.10)常用SQL优化 insert优化.order by 优化 1.insert 优化 2.order by 优化 [2.1]mysql排序方式: (1)索引扫描排序:通过有序索引扫描直接返回有 ...

  4. MYSQL常见可优化场景

    1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null 可以在num上设置 ...

  5. mysql常见优化,更多mysql,Redis,memcached等文章

    mysql常见优化 http://www.cnblogs.com/ggjucheng/archive/2012/11/07/2758058.html 更多mysql,Redis,memcached等文 ...

  6. MYSQL常见的可优化点

    MYSQL常见的可优化点 SQL常见的可优化点 2014年6月8日 DBA 发表回复 # #################################################### 索引 ...

  7. MySQL常见注意事项及优化

    MySQL常见注意事项 模糊查询 like 默认是对name字段建立了索引 注意:在使用模糊查询的时候,当% 在第一个字母的位置的时候,这个时候索引是无法被使用的.但是% 在其他的位置的时候,索引是可 ...

  8. Python进阶----索引原理,mysql常见的索引,索引的使用,索引的优化,不能命中索引的情况,explain执行计划,慢查询和慢日志, 多表联查优化

    Python进阶----索引原理,mysql常见的索引,索引的使用,索引的优化,不能命中索引的情况,explain执行计划,慢查询和慢日志, 多表联查优化 一丶索引原理 什么是索引:       索引 ...

  9. MySQL常见优化

    MySQL常见优化 1.操作符优化 1.1<> 操作符(不等于) 1.2LIKE优化 1.3in,not in,exists与not exists 1.3.1in和exists 2.whe ...

随机推荐

  1. hadoop2.6.0实践:控制台入口url列表

    hadoop web控制台页面的端口整理: 50070:hdfs文件管理 8088:ResourceManager 8042:NodeManager 19888:JobHistory(使用" ...

  2. 新概念英语(1-69)The car race

    新概念英语(1-69)The car race Which car was the winner in 1995 ? There is  car race near our town every ye ...

  3. Spring-Boot导入配置文件与取值

    前言: springboot简化了大量配置文件,但是必要时还是需要导入配置文件的,比如dubbo,此处简记之. 正文: 所有的配置文件引入都是使用注解在类上进行引入的,常用的有两种注解@Propert ...

  4. jvascript变量提升

    javascript变量提升 首先我们来看两个例子 var a = 1; function test(){ if(!a) var a = 10 alert(a) } test() //结果是10 是不 ...

  5. 前端插件之Bootstrap Switch 选择框开关控制

    简介 Bootstrap Switch是一款轻量级插件,可以给选择框设置类似于开关的样式 它是依赖于Bootstrap的一款插件 下载 下载地址 在线引用 导入 因为它是依赖于Bootstrap的一款 ...

  6. codeforces round 425 div2

    A. Sasha and Sticks 水题,判断一下次数的奇和偶就可以的. B. Petya and Exam 赛上的时候没有写出来,orz,记录一下吧. 题意:给出一个模式串,可能会有?和*两种符 ...

  7. requests+正则表达式爬取ip

    #requests+正则表达式爬取ip #findall方法,如果表达式中包含有子组,则会把子组单独返回出来,如果有多个子组,则会组合成元祖 import requests import re def ...

  8. angulajs_删除功能

  9. 我花了 8 小时,"掌握"了一下 Flutter | Flutter 中文站上线

    Hi,大家好,我是承香墨影! 距离 Google 在 2018 世界移动大会上发布 Flutter 的 Beta 版本,Flutter 是 Google 用以帮助开发者在 Android 和 iOS ...

  10. javaIO操作之字节输入流--InputStream

    /** *<li> InputStream类中定义的方法: * <li>读取的数据保存在字节数组中,返回读取的字节数组的长度:public int read(byte[] b) ...