UTF8:0-3 个字节
UTF8mb4:0-4 个字节

InnoDB:会自动建立主键索引
MyISAM:按插入顺序,不会建立索引

如果有主键,则用主键建立索引
如果没有主键
1、找唯一键,来建立索引
2、没有唯一键,使用 row_id 来建立索引(会耗费 6 个字节空间)

使用索引

  1. 最左前缀原则,也不能使用 like ‘%xxx%’ 前缀模糊匹配
  2. 网址使用索引查询,如:www.baidu.com,我们要查询 com 结尾的,根据最左前缀原则是无法使用到索引的,所以我们可以在存网址的时候,进行逆向存储:moc.udiab.www,此时,我们可以查询 like ‘moc%’ 即可
  3. 判断是否使用索引:辅助索引成本 + 回表成本
  1. -- 主键 a
  2. -- 联合索引 b,c,d
  3. select * from t where a = 1; -- yes
  4. select * from t where b = 1 and c = 1 and d = 1; -- yes
  5. select * from t where b > 1 and c > 1; -- no
  6. select * from t where b = 1 and c > 1; -- yes
  7. select * from t where a = 1 and b = 1;
  8. select * from t where a = 1 or b = 1;
  9. select * from t order by b, c, d; -- yes
  10. select * from t order by c, d; -- no
  11. select * from t where a = 1 order by c, d; -- yes
  12. select count(1) from t group by b, c, d; -- yes
  13. select count(1) from t group by c, d; -- no
  14. select count(1) from t where a = 1 group by c, d; -- yes
  15. select * from t order by b ASC, c ASC; -- yes
  16. select * from t order by b DESC, c DESC; -- yes
  17. select * from t order by b ASC, c DESC; -- no

索引的选择性 = 某列基数(不重复的记录值) / 某列记录数
选择性(0-1],选择性越大,越有建立索引的价值

前缀索引:如果联合索引在一起占用了太多空间,那么可以选择前缀索引,缺点是不能用 order by 和 group by

  1. select count(DISTINCT(first_name))/count(*) as selectivity
  2. from employees; -- 0.0042
  3. select count(DISTINCT(CONCAT(first_name, last_name)))/count(*) as selectivity
  4. from employees; -- 0.9313
  5. select
  6. count(DISTINCT(CONCAT(first_name, LEFT(last_name, 4))))/count(*) as selectivity
  7. from employees; -- 0.9007
  8. ALTER TABLE employees
  9. ADD INDEX `first_name_last_name_prefix` (first_name, last_name(4));

Join

优化的目的就是把 right join,left join 都优化成 inner join

inner join

  1. select * from t1, t2;
  2. select * from t1 join t2;
  3. select * from t1 inner join t2;

t1 和 t2 都可以作为驱动表,没有区别

join_buffer_size

一次取多条数据放入 join_buffer_size 中去,可以提高效率

  1. [mysqld]
  2. join_buffer_size = 16M