慷慨是不明智的,举例varchar(5)和varchar(200)存储‘Word’的空间是同样的,那为何又说慷慨是不明智的呢?实验证实更长的列会消耗更多的内存,由于mysql一般会分配固定大小的内存块来保存内部值。尤为是使用内存临时表进行排序或操做时会特别槽糕。因此最好的策略是只分配真正须要的空间。因此什么数据选择怎样的数据类型也是很重要的。对于钱,提一句,使用int或者bigint进行存储就够了。mysql
1.切分查询sql
有时候对于一个大查询咱们须要“分而治之”,将大查询切分红小查询,每一个查询功能彻底同样,值完成一小部分,每次只返回一下部分结果。删除旧的数据就是一个很好的列子。按期地清除大量数据时,若是用一个大的语句一次性完成的话,则可能须要一次锁住不少数据,占满整个事务日志,耗尽系统资源,阻塞不少小的但重要的查询。将一个大的delete语句切分多个较小的查询能够尽量小地影响mysql性能,同时还能够减小mysql复制的延迟。例如:咱们须要每月运行一次下面的查询:服务器
delete from message where create < date_sub(NOW(),INTERVAL 3 MONTH)
那么能够用相似下面的方法来完成:并发
rows_affected = 0 do { rows_affected = do_query( "delete from message where create < date_sub(NOW(),INTERVAL 3 MONTH) LIMIT 100000") }while rows_affected >0
一次删除一万行数据来讲是一个比较高效并且对服务器影响也最小的作法。同时,须要注意的是,若是是每次删除操做数据后,都暂停一下子再作下一次删除,这样也是能够的。函数
2.子查询和关联查询高并发
关联查询:post
select distinct id from film inner join actor using(film_id)
子查询:性能
select id from film where exists(select * from actor where film.id = actor.id);
进行性能对比发现:子查询比关联查询要快些。测试
总结: 一是不须要听取那些关于子查询的“绝对真理”,二是应该用测试来验证对子查询的执行计划和响应时间的假设。注意子查询有个bug,下面的写法会锁住table2中的一条记录:优化
select ... from table1 where col=(select ... from table2 where ...)
若是遇到该bug,子查询在高并发状况下的性能,就会和在单线程测试时的性能相差甚远。
3.在同一个表上查询和更新
mysql不容许对同一个表同时进行查询和更新。
4.优化特定类型的查询
4.1优化COUNT()查询
count()是一个特殊的函数,有两种很是不一样的做用:它能够统计某个列值的数量,也能够统计行数。在统计列值时要求列值是非空的(不统计null)。若是在count()的括号中指定了列或者列的表达式,则统计的就是这个表达式有值的结果数。
count()的另外一个做用是统计结果集的行数,当mysql确认括号内的表达式不可能为空时,实际上就是在统计行数。最简单的就是当咱们使用count(*)的时候,这种状况下通配符*并不会像咱们猜测的那样扩展成全部的列,实际上它会忽略全部的列而直接统计全部的行数。
简单的优化
咱们如何快速查找到全部ID大于5的城市:
select count(*) from city where id >5
经过结果能够看到该查询须要扫描4097行数据。若是将条件反转一下,先查找ID小于等于5的城市数,而后用总城市数一减就能获得一样的结果,却能够将扫描的行数减小到5行之内。
select (select count(*) from city)-count(*) from city where id <=5
5.延迟关联
延迟关联能够优化关联查询中的limit子句:
select id , name from film inner join(select id from film order by tilte limit 50,5) as lim using(id)
若是知道详细的位置,可使用下面的:
select id ,name from film where position between 50 and 54 order by postion;
假设查询返回的主键为16049 到 16030 的记录,那么下一页就能够从16030这个点开始:
select * from renal where id < 16030 order by id desc limit 20