count(*) 计数
myIsam count(*)很快,因为是直接保存的数目,但是加了where就不能很快返回了
InnoDB因为MVCC(单行多版本)的问题不适合计数,所以不能快速返回总数目
1.快速count(*)
1.使用缓存计数问题
1.缓存会丢失
2.数据不准确
2.在数据库保存计数
使用事务可以解决缓存问题
计数效率比较
count()>=count(1)>count(id)>count(字段)
count():被mysql优化过
尽量使用count(*)
redolog -binLog 两阶段提交
新行更新到内存
-> 写入redo log 处于prepare状态
-> 写入bin log
->提交事务,处于commit状态
redolog 是innodb特有日志,主要作用是崩溃恢复,但是由于循环
binLog 是mysql自有日志,支持日志归档
order by
CREATE TABLE `t` ( `id` int(11) NOT NULL, `city` varchar(16) NOT NULL,
`name` varchar(16) NOT NULL,
`age` int(11) NOT NULL,
`addr` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`), KEY `city` (`city`)
) ENGINE=InnoDB;
select city,name,age from t where city='杭州' order by name limit 1000 ;
全字段排序
1.sort_buffer初始化,确定放入所需字段
2.使用二级索引查询第一个符合条件的数据,从索引中获取主键
3.通过主键索引获取所需字段,放入sort_buffer
4.再次进入二级索引,查找符合要求下一个
5.重复3,4,查出所有符合要求的值
6.在sort_buffer中快速排序
7.(如果需要)分页
rowid排序
如果单行查询长度太大,mysql会使用另一种排序
1.sort_buffer初始化,确定放入所需字段
2.使用二级索引查询第一个符合条件的数据,从索引中获取主键
3.通过主键索引获取**主键和排序字段**,放入sort_buffer
4.再次进入二级索引,查找符合要求下一个
5.重复3,4,查出所有符合要求的值
6.在sort_buffer中快速排序
7.回表,使用id取出全部所需字段
8.(如果需要)分页
对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘读,因此不会被优先选择。
优化建议
1.不要对字段进行计算
select * from tradelog where id + 1 = 10000;
select count(*) from tradelog where month(t_modified)=7;
2.隐式类型转换
//判断mysql怎么进行数据类型转换,下面的字符串会转成数字,返回1
select “10” > 9;
3.隐式字符编码转换
两张表编码格式不一致也会导致全表查询。
为什么有些只查一行的数据,还是很慢
等MDL锁(在DDL和DML操作保持一致的锁)
等flush
等行锁
为什么有些只查一行的数据,还是很慢
(等元数据锁,等行锁,等flaush,没有索引)
脏读:一个事务读取到另一个未曾提交事务的数据
不可重复读:一个事务多次查询同一数据,得到的数据不一致
幻读:一个事务多次查询数据,后面查询得到前面未得到的数据