创建和删除:alter table stu add index idx_name(stu_name); # 创建索引alter table stu drop index idx_name; # 删除索引或者create index inx_name on stu(stu_name);drop index inx_name on stu;查询索引设置desc stu;
四、MySQL中的约束索引==主键索引==:
只能有一个主键。
索引:列的内容是唯一值,高中学号.
建的时候至少要有一个主键索引,最好和业务无关
走主键索引的查询效率是最高的,我们尽量每个表有一个主键,并且将来查询的时候计量以主键为条件查询
建表时创建推荐
CREATE TABLE `test` ( `id` INT(4) NOT NULL AUTO_INCREMENT, `name` CHAR(20) NOT NULL, PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=UTF8;
建立表后增加
CREATE TABLE `test1` ( `id` INT(4) NOT NULL, `name` CHAR(20) NOT NULL) ENGINE=INNODB DEFAULT CHARSET=UTF8; # 简历一个test1表ALTER TABLE test1 CHANGE id id INT(4) PRIMARY KEY NOT NULL AUTO_INCREMENT; # 增加自增主键
==普通索引==
加快查询速度,工作中优化数据库的关键。
在合适的列上建立索引,让数据查询更高效。
create index index_name on test(name);alter table test add index index_name(name);
用了索引,查一堆内容。
在where条件关键字后面的列建立索引才会加快查询速度.
select id,name from test where state=1 order by id group by name;
mysql> explain select name,gender,age from test where gender='F' and age <20;+----+-------------+-------+-------+---------------+----------+---------+------+------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+-------+---------------+----------+---------+------+------+-----------------------+| 1 | SIMPLE | test | range | inx_test | inx_test | 7 | NULL | 1 | Using index condition |
6.2、extra 列返回的描述的意义
1、Distinct : 一旦 MySQL 找到了与行相联合匹配的行,就不再搜索了。
2、Range checked for each Record(index map:#): 没有找到理想的索引,因此对于从前面表中来的每一个行组合,MySQL 检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一。
3、Using filesort : 看到这个的时候,查询就需要优化了。MySQL 需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。
4、Using index : 列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候。
5、Using temporary 看到这个的时候,查询需要优化了。这里,MYSQL 需要创建一个临时表来存储结果,这通常发生在对不同的列集进行 ORDER BY 上,而不是 GROUP BY 上 Where used 使用了 WHERE 从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型 ALL或 index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)。
6、system 表只有一行:system表。这是const连接类型的特殊情况
7、const : 表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为 MySQL 先读这个值然后把它当做常数来对待。
8、eq_ref : 在连接中,MySQL 在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用。
9、ref : 这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好。
10、range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
11、index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比 ALL 更好,因为索引一般小于表数据)。
12、ALL : 这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免
13、Not exists : MySQL 优化了LEFT JOIN,一旦它找到了匹配 LEFT JOIN 标准的行,就不再搜索了。
==出现Using temporary ,Using filesort ,Using join buffer 一般是排序 order by ,group by ,distinct,条件上没有索引例如: explain select * from city where countrycode='CHN' order by population; 或者在join 的条件列上没有建立索引== ==type : 表示MySQL在表中找到所需行的方式,又称“访问类型”,==
select * from tab; 全表扫描。 select * from tab where 1=1;
在业务数据库中,特别是数据量比较大的表。 是没有全表扫描这种需求。
1、对用户查看是非常痛苦的。
2、对服务器来讲毁灭性的。
(1)select * from tab;SQL改写成以下语句: selec * from tab order by price limit 10 需要在price列上建立索引(2) select * from tab where name='zhangsan' name列没有索引 1、换成有索引的列作为查询条件 2、将name列建立索引
查询结果集是原表中的大部分数据,应该是30%以上。
查询的结果集,超过了总数行数30%,优化器觉得就没有必要走索引了。
假如:tab表 id,name id:1-100w ,id列有索引select * from tab where id>500000;如果业务允许,可以使用limit控制。怎么改写 ? 结合业务判断,有没有更好的方式。如果没有更好的改写方案 尽量不要在mysql存放这个数据了。放到redis里面。
索引本身失效,统计数据不真实
索引有自我维护的能力。 对于表内容变化比较频繁的情况下,有可能会出现索引失效。
查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)
例子: 错误的例子:select * from test where id-1=9; 正确的例子:select * from test where id=10;
错误的例子:select * from test where tu_mdn=13333333333; 正确的例子: select * from test where tu_mdn='13333333333';
<> ,not in 不走索引
EXPLAIN SELECT * FROM teltab WHERE telnum <> '110';EXPLAIN SELECT * FROM teltab WHERE telnum NOT IN ('110','119');------------mysql> select * from tab where telnum <> '1555555';+------+------+---------+| id | name | telnum |+------+------+---------+| 1 | a | 1333333 |+------+------+---------+1 row in set (0.00 sec)mysql> explain select * from tab where telnum <> '1555555';
单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽量结合业务添加limit or或in 尽量改成union
EXPLAIN SELECT * FROM teltab WHERE telnum IN ('110','119'); 改写成:
EXPLAIN SELECT * FROM teltab WHERE telnum='110' UNION ALL SELECT * FROM teltab WHERE telnum='119'
like "%_" 百分号在最前面不走
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' 走range索引扫描EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' 不走索引%linux%类的搜索需求,可以使用elasticsearch