sql语句优化
一、定位慢查询:
必要指令:
show status like ‘uptime’;当前数据库运行多久
show session或global status like ‘com_select’;当前数据库运行多少次查询
show session或global status like ‘com_update’;当前数据库运行多少次更新
show session或global status like ‘com_delete’;当前数据库运行多少次删除
show session或global status like ‘com_insert;当前数据库运行多少次查询
默认是session,意思是当前会话的操作次数
global是所有的操作次数
根据数据库的操作类型来决定使用什么存储引擎
show status like ‘connections’;当有多少客户端连接数据库
show status like ‘slow_queries’;查询有多少慢查询
默认情况,mysql认为查询时间到达10秒才是一个慢查询
show variables like ‘long_query_time’;显示慢查询定义时间
set long_query_time=1;将慢查询定义时间设置为1秒
查询方法:
1.停止mysql服务,在计算机管理–>服务–>mysql中停止
2.在默认情况下mysql不记录慢查询日志,需要在启动的时候指定
bin\mysqld.exe - -safe-mode - -slow-query-log [mysql5.5 可以在my.ini指定]
bin\mysqld.exe –log-slow-queries=d:/abc.log [低版本mysql5.0可以在my.ini指定]
(在bin的上级目录打开cmd再执行)
启用慢查询日志后,默认把日志文件放在my.ini文件中记录的位置
在文件中搜索:“datadir=”;
不要轻易更改此目录,会造成索引失效。
3.set long_query_time=1;将慢查询定义时间设置为1秒
4.show status like ‘slow_queries’;查询有多少慢查询
5.查日志就可以把慢查询揪出来了
二、索引:
索引为毛这么快:
1.没有索引时,需要全表检索,即使很早检索到数据也必须搜完所有表;
2.加完索引后,会建立一个索引文件,这个索引文件会将索引字段的磁盘地址构建成一个二叉树的数据结构进行存储,搜索时会进行二分查找,一旦查找到要查的数据就不需要找更下级的数据了,这样就大大加大了查询速度。
经过计算:检索10次可以检索1024条数据,检索30次可以检索10亿的数据
主键索引:
创建:
1.当一张表,把某个列设置为主键时,则该列就是主键索引
2.alter table 表名 add primary key (列名);
查询:
1.desc 表名; 该方法缺点是:不能够显示索引名
2.show index(es) from 表名;
3.show keys from 表名;
唯一索引:
1.当表的某列被指定为unique约束时,这列就是一个唯一索引
create table ddd(id int primary key auto_increment , name varchar(32) unique);
这时, name 列就是一个唯一索引.
unique字段可以为NULL,并可以有多NULL, 但是如果是具体内容,则不能重复.
主键字段,不能为NULL,也不能重复.
2.在创建表后,再去创建唯一索引
create table eee(id int primary key auto_increment, name varchar(32));
create unique index 索引名 on 表名 (列表…);
全文索引:
应用场景:针对文本(文件)的检索,全文索引仅针对MyISAM有用
创建:
CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) )engine=myisam charset utf8;
使用:
1.在mysql中fulltext 索引只针对 myisam生效
2.mysql自己提供的fulltext针对英文生效->sphinx (coreseek) 技术处理中文
3.使用方法是 match(字段名…) against(‘关键字’)
4.全文索引一个 叫 停止词, 因为在一个文本中,如果使用常用词创建索引是一个无穷大的数,因此,对一些常用词和字符,就不会创建,这些词,称为停止词.
普通索引:
创建:
先创建表再创建普通索引
create index 索引名 on 表名 (列);
1
索引删除及修改:
删除
alter table 表名 drop index 索引名;
如果删除主键索引。
alter table 表名 drop primary key [这里有一个小问题]
修改
先删除,再重新创建.
索引的使用方法:
在如下情况添加索引比较合适:
a: 经常作为where条件被使用
b: 该字段的内容不是唯一的几个值(sex)
c: 字段内容不是频繁变化
会导致索引失效的语句:
1、使用like关键字模糊查询时,% 放在前面索引不起作用,只有“%”不在第一个位置,索引才会生效(like ‘%文’–索引不起作用)
2、使用联合索引时,只有查询条件中使用了这些字段中的第一个字段,索引才会生效
3、使用OR关键字的查询,查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,索引才会生效,否则索引不生效。
4、尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。
5、对查询进行优化,应尽量避免全表扫描,首先应考虑在where以及order by涉及的列上建立索引。
6、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
7、尽量避免在where子句中对字段进行函数操作,将导致引擎放弃使用索引而进行全表扫描。
8、不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
9、并不是所有的索引对查询都有效,sql是根据表中的数据来进行查询优化的,当索引列有大量数据重复时,sql查询不会去利用索引,如一表中有字段
sex,male,female几乎个一半,那么即使在sex上建立了索引也对查询效率起不了作用。
10、索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,
若太多则应考虑一些不常使用到的列上建的索引是否有 必要。
11、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接时会 逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
12、mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。
因此数据库默认排序可以符合要求的情况下不要使用排序操作,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引。
13、order by 索引 ,不起作用的问题(除了主键索引之外):
1、 如果select 只查询索引字段,order by 索引字段会用到索引,要不然就是全表排列;
2、如果有where 条件,比如where vtype=1 order by vtype asc . 这样order by 也会用到索引!
四种索引的使用场景:
PRIMARY, INDEX, UNIQUE 这3种是一类
PRIMARY 主键。 就是 唯一 且 不能为空。
INDEX 索引,普通的
UNIQUE 唯一索引。 不允许有重复。
FULLTEXT 是全文索引,用于在一篇文章中,检索文本信息的。
举个例子来说,比如你在为某商场做一个会员卡的系统。
这个系统有一个会员表
有下列字段:
1. 会员编号 INT 2. 会员姓名 VARCHAR(10) 3. 会员身份证号码 VARCHAR(18) 4. 会员电话 VARCHAR(10) 5. 会员住址 VARCHAR(50) 6. 会员备注信息 TEXT
那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息 , 如果需要建索引的话,可以选择 FULLTEXT,全文搜索。
不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
三、搜索引擎的选择:
1、MYISAM:默认的MySQL存储引擎。如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性要求不是很高。其优势是访问的速度快。重要性不高的数据,如论坛的发帖、回帖。
2、Innodb:提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM,写的处理效率差一些并且会占用更多的磁盘空间。重要性较高的数据,如订单表、工资表。
3.Memory:存储在内存当中,速度快,但会占用和数量成正比的内存空间且数据在mysql重启时会丢失。经常变化、查询频繁的临时数据。
四、explain分析SQL:
Explain select * from emp where ename=“zrlcHd”会产生如下信息:
select_type:表示查询的类型。
table:输出结果集的表
type:表示表的连接类型
possible_keys:表示查询时,可能使用的索引
key:表示实际使用的索引key_len:索引字段的长度rows:扫描出的行数(估算的行数)
Extra:执行情况的描述和说明
五、常用SQL优化:
1.优化group by 语句
默认情况,MySQL对所有的group by col1,col2进行排序。这与在查询中指定order by col1, col2类似。如果查询中包括group by但用户想要避免排序结果的消耗,则可以使用order by null禁止排序
2.有些情况下,可以使用连接来替代子查询。因为使用join,MySQL不需要在内存中创建临时表。
3.如果想要在含有or的查询语句中利用索引,则or之间的每个条件列都必须用到索引,如果没有索引,则应该考虑增加索引
select * from 表名 where 条件1=‘’ or 条件2=‘tt’