MySQL索引和优化查询

恰当的索引可以加快查询速度,可以分为四种类型:主键、唯一索引、全文索引、普通索引。

主键:唯一且没有null值。
create table pk_test(f1 int not null,primary key(f1));
alter table customer modify id int not null, add primary key(id);

普通索引:允许重复的值出现。
create table tableanme (fieldname1 columntype,fieldname2 columntype,index [indexname] (fieldname1 [,fieldname2...]));
create table tablename add index [indexname] (fieldname1 [fieldname2...]);
alter table slaes add index(value);

全文索引:用来对大表的文本域(char,varchar,text)进行索引。语法和普通索引一样-fulltext。
使用全文索引:create table ft2 (f1 varchar(255),fulltext(f1));
insert into ft2 values(‘wating for the bvarbariands‘),(‘in the heart of the country‘),(‘the master of petersburg‘),(‘writing and being‘),(‘heart of the beast‘),(‘master master‘);
select * from ft2 where match(f1) against(‘master‘); // match()-匹配域;against()匹配值。
MySQL会对某些字忽略,造成查询的误差:a. 50%以上的域出现的单词;b.少于三个字的单词;c.mysql预定义的列表,包括the。
查询语句:select * from ft2 where match(f1) against(‘the master‘); // 与希望的结果是不同的
相关性分数查询:select f1,(match(f1) against(‘master‘)) from ft2;
mysql4的新功能-布尔全文查询:select * from ft2 where match(f1) against(‘+master -pet‘ in boolean mode); // 运算符类型 +-<>()~*"


唯一索引:除了不能有重复的记录外,其它和普通索引一样。
create table ui_test (f1 int,f2 int,unique(f1));
alter table ui_test add unique(f2);
对域(varchar,char,blob,text)的部分创建索引:alter table customer add index (surname(10));
自动增加域:每次插入记录时会自动增加一个域的值,只能用于一个域,且这个域有索引。
create table tablename(fieldname int auto_increment,[fieldname2...,] primary key(filedname));
alter table tablename modify fieldname columntype auto_increment;
last_insert_id()函数返回最新插入的自动增加值。
select last_insert_id() from customer limit 1;
此函数在多个连接同时进行时,会发生错误。
重置自动增加计数器的值:
create table tablename(fieldname int auto_increment,[fieldname2...,] primary key(filedname) auto_increment=50);
alter table tablename auto_increment=50;
如果重置的值比存在的值小,自动增加计数器会从记录中最大的那个值开始增加计数,比如customer表中的id已经有1、2、3、15、16、20,当把自动增加计数器的值设为1时,下次插入的记录会从21开始。
自动增加计数器的越界:有效值为1~2的127次方,即2147483647。如果超过这个值(包括负值),mysql会自动把它设为最大值,这样就会产生一个重复键值的错误。
自动增加域在多列索引中的使用:
create table staff(rank enum(‘employee‘,‘manager‘,‘contractor‘) not null,position varchar(100),id int not null auto_increment,primary key(rank,id));
insert into staff(rank,position) values(‘employee‘,‘cleaner‘),(‘cotractor‘,‘network maintenance‘),(‘manager‘,‘sales manager‘);
在对每个级别添加一些数据,会看到熟悉的自动增加现象:
insert into staff(rank,position) values(‘employee‘,‘cleaner1‘),(‘employee‘,‘network maintenance1‘),(‘manager‘,‘sales manager1‘);
在这种情况下是不能重置自动增加计数器的。
删除或更改索引:对索引的更改都需要先删除再重新定义。
alter table tablename drop primary key;
alter table table drop index indexname;
drop index on tablename;


高效使用索引:下面讨论的是用了索引会给我们带来什么?
1.) 获得域where从句中匹配的行:select * from customer where surname>‘c‘;
2.) 查找max()和min()值时,mysql只需在排序的索引中查找第一个和最后一个值。
3.) 返回的部分是索引的一部分,mysql就不需要去查询全表的数据而只需看索引:select id from customer;
4.) 对域使用order by的地方:select * from customer order by surname;
5.) 还可以加速表的连接:select first_name,surname,commission from sales,sales_rep wheresales.sales_rep=sales_rep.employee_number and code=8;
6.) 在通配符的情况下:select * from sales_rep where surname like ‘ser%‘;
这种情况就不能起作用:select * from sales_rep where surname like ‘%ser%‘;
选择索引:
1.) 有查询需要使用索引(比如where从句中条件的域)的时候,要创建索引;不要不使用的域(不如第一个字符是通配符的)创建索引。
2.) 创建的索引返回的行越少越好,主键最好,枚举类型的索引不什么用处。
3.) 使用短索引(比如,名字的头十个字符而不是全部)。
4.) 不要创建太多的索引,虽然加快了查询的速度,但增加了更新的添加记录的时间。如果索引在查询中很少使用,而没有索引只是轻微的影响速度,就不要创建索引。
最左边规则:这种情况发生在多个有索引的域上,mysql从索引列表的最左边开始,按顺序使用他们。
alter table customer add initial varchar(5);
alter table customer add index(surname,initial,first_name);
update customer set initial=‘x‘ where id=1;
update customer set initial=‘c‘ where id=2;
update customer set initial=‘v‘ where id=3;
update customer set initial=‘b‘ where id=4;
update customer set initial=‘n‘ where id=20;
update customer set initial=‘m‘ where id=21;
如果在查询中使用了这三个域,那就最大限度的利用了索引:select * from customer where surname=‘clegg‘ and initial=‘x‘ and first_name=‘yvonne‘;
或者是利用索引的大部分:select * from customer where surname=‘clegg‘ and initial=‘x‘;
或仅仅是surname:select * from customer where surname=‘clegg‘;
如果打破最左边规则,下面的例子就不会用到索引:select * from customer where initial=‘x‘ and first_name=‘yvonne‘;
select * from customer where initial=‘x‘ ;
select * from customer where first_name=‘yvonne‘;
select * from customer where surname=‘clegg‘ and first_name=‘yvonne‘;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/0bc5331a59bf2e5d73e8604121776493.html