高性能Mysql

第五章:高性能的索引策略

1.什么是索引?

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。

2.使用索引的好处

1.索引大大减少了服务器需要扫描的数据量。

2.索引可以帮助服务器避免排序和临时表

3.索引可以将随机IO变成顺序IO

索引建立得越多就越占磁盘空间,在更新数据的时候速度会更慢。

 3.聚簇索引和非聚簇索引

聚簇索引:实际存储的循序结构与数据存储的物理机构是一致的,所以通常来说物理顺序结构只有一种,那么一个表的聚簇索引也只能有一个,通常默认都是主键,

设置了主键,系统默认就为你加上了聚簇索引,当然有人说我不想拿主键作为聚簇索引,我需要用其他字段作为索引,当然这也是可以的,

这就需要你在设置主键之前自己手动的先添加上唯一的聚簇索引,然后再设置主键,这样就木有问题啦。

非聚簇索:引记录的物理顺序与逻辑顺序没有必然的联系,与数据的存储物理结构没有关系;

一个表对应的非聚簇索引可以有多条,根据不同列的约束可以建立不同要求的非聚簇索引

4.索引什么时候会失效

如果查询中的列不是独立的,则MySQL就不会使用索引。

“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。

如select id from table where id+1=5;

我们应该简化where条件的习惯,始终将索引列单独放在比较符的一侧

 

5.索引的一些建议

很长的字符列,可以索引开始的部分字符。

索引中数据列顺序的选择(选择性高的放在左边)

 

6.InnoDB和MyISAM总结和对比

InnoDB

1.支持ACID事务,支持存储过程,试图,支持行级锁定,支持外键,处理巨大数据量时拥有最大性能

 

应用场景

1.以insert、update为主的应用

2.在需要高性能的大型数据库中的应用。

3.更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。

4.事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎

5.自动灾难恢复。与其他存储引擎不同,InnoDB表能够自动从灾难中恢复

6.外键约束。MySQL支持外键的存储引擎只有InnoDB

7.支持自动增加列AUTO_INCREMENT属性

 

MyISAM

较高的查询速度,表级锁定;BLOB和TEXT列可以被索引;不支持事务;不支持外键,支持全文引,

应用场景:

对事务完整性没有要求或者select为主的应用。

无事务要求,但对效率要求比较高的应用。

 

7.覆盖索引

一个包含查询所需字段的索引称为“覆盖索引”
覆盖索引的好处:
1.索引的条目通常远小于数据行的大小,所以如果只需要读取索引,就极大的减少数据访问量。
2.因为索引是按照顺序存储的,所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少很多。
3.由于InnoDB的聚簇索引,覆盖索引对InnoDB特别有用。InnoDB的二级索引在叶子节点中保存了主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。

 

8.使用索引扫描来做排序

mysql可以使用同一个索引既满足排序,又用于查找行,因此,如果可能,设计索引时应该尽可能地同时满足这两种任务,这样是最好的。
只有当索引的列顺序和order by子句的顺序完全一致,并且所有列的排序方向(倒序或升序,创建索引时可以指定ASC或DESC)都一样时,mysql才能使用索引来对结果做排序,
如果查询需要关联多张表,则只有当order by子句引用的字段全部为第一个表时,才能使用索引做排序,order by子句和查找型查询的限制是一样的,需要满足索引的最左前缀的要求,

否则mysql都需要执行排序操作,而无法使用索引排序。

不能使用索引排序的查询
1.查询使用了不同的排序方向,索引列都是正序定义的。
2.排序字段不在索引列。
3.无法组成最左前缀。
4.某个列有范围查询。

 

9.冗余索引

冗余索引:如果创建了索引(A,B),再创建索引(A)就是冗余索引,因为这只是前一个索引的前缀索引。

 

第六章:查询性能的优化


1.是否向数据库请求了不需要的数据

    常见案例及解决思路:
             查询不需要的记录(考虑使用limit)
             多表关联时返回全部列(只取需要的列,避免使用select *)
             总是取出全部列(避免select *)
             重复查询相同数据(使用缓存,避免多次查询同样数据)

    小插曲:关于查询缓存

Mysql query cache 默认为打开。
如果有大量的修改和查询时,由于修改造成的cache失效,会给服务器造成很大的开销,可以通过
query_cache_type{0(OFF)1(ON)2(DEMAND)}来控制缓存的开关.
  何时cache
 1)两个sql必须完全一致才会导致cache命中,包括大小写
 2)prepared statement永远不会cache到结果,即使参数完全一样。据说在 5.1 之后会得到改善。
 3)where条件中如包含了某些函数永远不会被cache, 比如current_date, now等。
 4)   date 之类的函数如果返回是以小时或天级别的,最好先算出来再传进去。
select * from foo where date1=current_date -- 不会被 cache
select * from foo where date1='2008-12-30' -- 被cache, 正确的做法
5) 太大的result set不会被cache (< query_cache_limit)

cache何时失效
1)一旦表数据进行任何一行的修改,基于该表相关的cache立即全部失效。
2)查询为了返回结果是否扫描了过多的数据


3.重构查询方式


   1)是否将一个复杂查询分成多个简单查询
    2)切分查询。 例如:定期删除大量数据时,如果用一个大的语句一次完成,可能需要锁住很多数据,占满整个事务日志,耗尽系统资源、阻塞很多小的但是重要的查询。
    3)分解关联查询:很多高性能应用都会对关联查询进行分解。简单的,可以对每一个表进行一次单表哈寻,然后将结果在应用汇总关联。
                          select * from tag join tag_post on tag_post.tag_id=tag.id join post ontag_post.id=post.id where tag.tag='mysql';
                       分解成小查询
                              select * from tag where tag='mysql'
                              select * from tag_post where tag_id=1234
                               select * from post where post.id in (123m456m789,9098)
                        然后通过应用来将多个结果集合并。

 

4.对一些特定类型的优化查询

 

对于MyISAM存储引擎,在表单中没有限定where查询条件时count(*)是非常快的,因为myisam本身已经存储这个行数总值。当存在where限定条件,也需要进行查询统计的。

下面给出一个简单的优化使用示例:

(1)优化一:

explain select count(*) from item where id > 100;

explain select (select count(*) from item) - count(*) from item where id <100;

尽量少用子查询,因为子查询会产生零时表

group by 和 distinct优化

group by 和 distinct的优化最有效的就是使用索引。

当无法使用索引时,group by使用两种策略完成:零时表或者文件排序来做分组。

所以对于分组的列一定要建立索引。比如

Select product, count(*) from orders group by product

这样一个查询,对product要建立索引。

(2)limit分页优化

进行分页操作时,通常都会通过偏移量来查询某些数据。然后再加上解释的order by,性能一般都不错。
对于order by的列 一定要加上索引。
但是对于limit 10000, 10 这样检索目标10条记录必须先先查询前面的10000条记录。代价很高,这种时候优化最简单办法就是使用覆盖索引。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务