一.mysql索引分为btree索引和hash索引。
btree索引是二叉树结构 先到索引树上找,再去根据索引到数据里边找数据。
hash索引是memory引擎,精准查询非常快,如果查范围内(where>8),会比较慢。因为是无序的,无法使用前缀索引。
2.btree索引
建立索引,通常是经常用到做查询条件,做分组,做排序。
独立索引,单个建索引只能用一个索引,通常用联合索引。 如建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销
3.聚簇索引(innodb)和非聚簇索引(myisam),都用的是btree索引,但细节有不同。
非聚簇索引:myisam数据和索引树是分开的,你要先找数据先到索引树上找,找到之后再去数据上要数据。
聚簇索引:innodb 的数据和索引直接放在一起,当你找到索引树上找到时,数据也找到了,不要回行。(数据和索引挤在一块),innodb 次级索引,指向主键的索引,主键索引即存储索引,也存数据。(不需要回行,如果不规则数据插入会造成页分裂)
页分裂:主键没有规律,或者叶子(如varchar(10000))比较大(比较慢)
4. 理想的索引
1查询频繁,2区分度高(去重查询的数据/总count数据=1)。如(男,女区分度不高。就没有必要建索引),3索引长度
多列索引:1查询的频率,2区分度,3列的顺序(具体根据业务需求)
5.伪哈希索引,左前缀不好区分的列建立索引。如一列 url 存储www.baidu.com,www.weibo.com 入库的时间,可以加一个字段 crc 插入数据的时候添加crc32,转成32位的整数。
6.索引与排序(最后索引覆盖排序,如果没有用上索引,那么排序会生成一个临时表,要排序)
7.修复表(索引碎片与维护),数据在磁盘空间,不断的加入和修改。就会有碎片
可以1. alert table xxx engine innodb (如果表是innodb) 2.optimize table 表名
二.SQL语句优化 (查的快,取的快,传的少)
执行sql 一个是等待时间,一个是执行时间
查询时间 一个是查找(索引),二是数据取出返回(send_data,不回行,索引覆盖,传的少)
1.原则,不查,少查,走索引,覆盖索引
2.大数据,拆分查询,能不连表就不连表(联查数据多了)
3.explain 解析sql语句
1. 关键部分 type 索引发挥的作用怎么样(
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。
)
2.possible_keys 估计用到的索引
3.key 用到的索引 (显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL)
4.rows 大概查询的行
5.Extra:包含MySQL解决查询的详细信息,也是关键参考项之一
Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了Not exists
MYSQL 优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
Range checked for each
Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一 个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一Using filesort
看 到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来 排序全部行Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表 的全部的请求列都是同一个索引的部分的时候Using temporary
看到这个的时候,查询需要优化了。这 里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index, 这就会发生,或者是查询有问题
4.查看mysql运行时间
show variables like "%pro%";
设置开启方法: set profiling = 1;
show profiles 查看执行sql语句的情况
三 mysql 分页优化。
如果一个表数据2千万条,分页的时候从10万页 取10条
或许你就 limit 100000,10 这样性能就非常差。(mysql会查找前面10万页的数据和后面10条数据,然后再丢掉前边的10万条数据)
解决方案: 1根据实际情况,不让进行这么多的分页,如最大100页。(没必要翻那么多页,可以换一个关键词)
2根据索引 ,如数据表不删除除,只做逻辑删除。where id >100000 limit 100000 ,10 这里用到索引就比较快