查看MySQL是如何执行语句的:explain
use sql_store;
explain select customer_id
from customers
where sql_store.customers.state = 'CA'
命名:idx_列名
create index idx_state on customers(state);
创建索引后执行explain:
练习:查询积分大于1000的顾客
没有创建索引时:type为all,row为1010
explain select customer_id
from customers
where points > 1000;
为points列创建索引:type为range,rows为529
create index idx_points on customers(points);
explain select customer_id
from customers
where points > 1000;
drop index idx_state on customers;
show indexes in customers;
key_name:索引 / 键名
collation:排序方式,A为升序,D为降序。
cardinality:基数。
表示索引中唯一值的估计数量。此数值是估量,不是真实值。
analyze table 表名:生成关于此表的统计信息;执行后再执行查看索引语句即可获取真实值。
analyze table customers;
index_type:索引类型
为两张表创建一组关系时,MySQL会自动为外键创建索引,这样就可以快速连接表。
查看orders表的索引,发现外键都有二级索引。
show indexes in orders;
使用前缀索引的原因:
创建前缀索引:
create index idx_lastname on customers(last_name(20))
索引的选择性指不重复的索引值与数据总量的比值
select count(*) from customers;
select
count(distinct left(last_name, 1))/count(*) as selectivity1,
count(distinct left(last_name, 5))/count(*) as selectivity5,
count(distinct left(last_name, 10))/count(*)as selectivity10
from customers;
截取前5个字符时由95.6%的数据不同,可以选择前5个字符为前缀创建前缀索引。
索引的选择性在80%以上适合建立,否则不建议建立索引,例如性别等。
use sql_blog;
select *
from posts
where title like '%react redux%' or
body like '%react redux%';
use sql_blog;
create fulltext index idx_title_body on posts(title, body);
select *
from posts
where match(title, body) against('react redux');
select *,
match(title, body) against('react redux') as score
from posts
where match(title, body) against('react redux');
默认情况的模式。只包含react、只包含redux、包含react和redux,以上三种情况。
select *,
match(title, body) against('react redux') as score
from posts
where match(title, body) against('react redux');
可以包括或排除某些单词
against(‘text1 -text2 -text3’ in boolean mode)
例如:
负号:包括react,不包含redux的行
select *
from posts
where match(title, body) against('react -redux' in boolean mode);
正号:包括react,不包含redux,每一行必须有form
select *
from posts
where match(title, body) against('react -redux +form' in boolean mode);
场景:搜索位于加州且积分大于1000的顾客
use sql_store;
show indexes in customers;
explain select customer_id
from customers
where state = 'CA' and points > 1000;
允许对多列建立索引,可优化查询。
可以在state列和points列上创建复合索引,可以快速找到位于任何州、拥有任意积分的数据
use sql_store;
create index idx_state_points on customers(state, points);
explain select customer_id
from customers
where state = 'CA' and points > 1000;
此时的查询需要扫描58行,之前需要扫描112行。
可能的键:有3个,state上、points上、state和points上的复合索引,复合索引在优化查询上更好,因此最后选择了复合索引进行查询
一个索引中最多可包含16列,一般在4-6列能达到很好的性能,但最终应根据实际查询和数据量进行确定。
在from和where中间使用use index(索引名称)
explain select customer_id
from customers
use index(idx_lastname_state)
where state = 'NY' and last_name like 'A%';
有些情况下,即使有索引,但仍会遇到性能问题
用 or 进行条件查询:
explain select customer_id
from customers
where state = 'CA' or points > 1000;
重写查询,以尽可能最好的方式利用索引。把查询拆分成两段更小的查询。
选择所有位于加州的顾客,和另一个选择了超过1000积分的数据进行联合查询。
但第二段points查询,在idx_state_points索引上位于第二列,查询效率也不高。因此要在points列上创建单独的索引。
两端查询rows为112+529,比1010少了很多。
create index idx_points on customers(points);
explain
select customer_id from customers
where state = 'CA'
union
select customer_id from customers
where points > 1000;
想要利用索引,需要单独把列提出来
explain select customer_id from customers
where points - 10 > 2010;
explain select customer_id from customers
where points > 2000;
例子,按顾客所在的州对其进行排序
-- 按使用了索引的列进行排序
explain select customer_id from customers
order by state;
-- 按没有使用索引的列进行排序
explain select customer_id from customers
order by first_name;
结果:第一个type是index,按照state在前的索引进行排序。第二个type为all,进行全表扫描,使用外部排序。
基本规则
explain select * from customers
order by state;