/*创建索引*/
create index index_name on t_user(name);
/*删除索引*/
drop index index_name on t_user;
全值匹配
全值匹配,对索引中所有列都指定具体值。改情况下,索引生效,执行效率高。
explain select * from t_user where name='Himit_ZH' and status='1' and address='广东'\G;
最左前缀法则
联合索引中,在创建索引的顺序中的索引必须左边索引都必要出现,先后顺序无关,但必须出现,不能跳过,例如 name,status,address只能出现以下情况
create index idx_seller_name_sta_addr on t_user(name,status,addresss);
/* 以下都会走索引 */
select * from t_user where name='Himit_ZH'
select * from t_user where name='Himit_ZH' and status='1'
select * from t_user where name='Himit_ZH' and status='1' and address='广东'\G;
select * from t_user where status='1' and address='广东' and name='Himit_ZH'\G;
范围查询右边的列,不能使用索引。
// 后面的 address的索引会失效。
select * from t_user where name='Himit_ZH' and status>'1' and address='广东'\G;
索引列上不能使用运算操作,否则索引失效。
// 如此查询,索引将失效。
select * from t_user where substring(name,6,2)='ZH';
字符串不加单引号,索引失效。
// name走索引,但是status不走索引
select * from t_user where name ='Himit_ZH' and status = 1
// name和status都走索引
select * from t_user where name ='Himit_ZH' and status = '1'
尽量使用覆盖索引,避免使用select *
select * from t_user where name='Himit_ZH'
用到了索引,但是由于是select * 还会到表结构查询相应的行数据。
select name from t_user where name='Himit_ZH'
此时查询的字段name在B+树中已经存了数据,不需要回表查询了。
select name,sex from t_user where name='Himit_ZH'
此时查询的字段多了一个sex,并没有为这个字创建索引,此时又会发生回表查询。
用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。(and 会走索引)
例如:name有索引,sex没有索引。
explain select name,sex from t_user where name='Himit_ZH' or sex='男'
进行了全文扫描,并未走索引查询。
使用%模糊匹配时,%出现在模糊字符串前面不走索引,例如%ZH
或者%ZH%
,但是ZH%
只在后面会走索引。
explain select * from t_user where name like '%Himit_ZH%'
解决方法:使用覆盖索引,即获取的查询字段都有建立索引。(name,address,status)
explain select name,address,status from t_user where name like '%Himit_ZH%';
有可能SQL判断走索引比全文扫描慢,就不会走索引。
is NULL或者is not NULL 有时候
不走索引,都是MySQL底层会进行字段判断,看执行效率是否需要走索引还是走全文扫描。
in走索引,not in不走索引。
explain select * from t_user where id in (1,2);
explain select * from t_user where id not in (1,2);
尽量使用复合索引,少用单列索引。
相当于创建了name和sex索引,这样无论出现单个name,sex还是同时出现,都走一个索引。
create index idx_name_sex on t_user(name,sex)
这样创建,如果两个索引条件同时出现,MySQL只会走一个最优索引,而不是两个索引。
create index idx_name on t_user(name)
create index idx_sex on t_user(sex)
show status like 'Hander_read%';
show global status like 'Hander_read%';
explain分析,表中的type是访问类型,效率从高到低如下:
system > const > eq_ref > ref > fulltext > ref_or_null >index_merge > unique_subque> index_subquery>range > index > ALL
1)批量插入数据主键最好有序,这样InnoDB引擎创建B+树索引时效率更快。
load data local infile '文件位置' into table '表名' fields terminated by ',' lines terminated by '\n';
2)关闭唯一性校验
插入数据前关闭唯一性校验
SET UNIQUE CHECKS=0;
插入后重新开启
SET UNIQUE CHECKS=1;
3)手动提交事务
插入数据前关闭自动提交事务
SET AUTOCOMMIT=0;
插入后再开启
SET AUTOCOMMIT=1;
多行数据时使用
insert into t_user values(...),(...),...
按主键顺序插入
insert into t_user values(1,..),(2,..),...
查询的字段有创建索引,也就是覆盖索引时,order by会走索引排序,而非全文排序,例如 age,id有索引。
select age,id from t_user order by age;
但若是select * 会走filesort
select * from t_user order by age;
多字段排序时,必须同升同降,一升一降会导致走filesort,同升同降才会走索引排序。
select age,id from t_user order by age asc,id desc;
group by默认会使用filesort排序,如果不想排序,再分组后面加上order by null,关掉会提高分组效率。
select age,id from t_user group by age order by null;
explain select * from t_user where in (select id from user_role);
explain select * from t_user u,user_role ur where u.id=ur.user_id;
可以看到type变成ref,比index效率更高,所以建议使用多表查询。
建议使用union替换or
explain select * from t_user where id =1 or id=10;
explain select * from t_user where id =1 union select * from t_user where id =10;
type的const的效率远高于range。
explain select * from tb_item limit 200000,10;
explain select * from tb_item t,(select id from tb_item order by id limit 200000,10) a where t.id=a.id;
explain select * from tb_item id > 200000 limit 10;
USE INDEX 提示建议MySQL使用指定的索引
select * from t_user use index(idx_name) where name = 'Himit_ZH'
IGNORE INDEX 提示忽略使用指定索引
select * from t_user ignore index(idx_id) where name = 'Himit_ZH'
FORCE INDEX 强制使用索引
select * from t_user force index(idx_name) where name = 'Himit_ZH'
ACID属性:
事务并发的问题:
问题 | 含义 |
---|---|
丢失更新(Lost Update ) | 当两个或多个事务选择同一行,最初的事务修改的值,会被后面的事务修改的值覆盖。 |
脏读(Dirty Reads ) | 当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。 |
不可重复读〔Non-Repeatable Reads ) | 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现和以前读出的数据不一致。 |
幻读(Phantom Reads ) | 一个事务按照相同的查询条件重新读取以前查询过的数据,却发现其他事务插入了满足其查询条件的新教据。 |
InnoDB实现了以下两种类型的行锁。
对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);
对于普通SELECT语句,innoDB不会加任何锁;
手动加锁
共享锁(S): SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(x): SELECT * FROM table_name WHERE ... FOR UPDATE