Mysql 查询数据慢,加入索引

1. 索引操作[转] http://xitong.iteye.com/blog/1822220

创建索引

在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引。

1.ALTER TABLE

ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。

ALTER TABLE table_name ADD INDEX index_name (column_list)

ALTER TABLE table_name ADD UNIQUE (column_list)

ALTER TABLE table_name ADD PRIMARY KEY (column_list)

其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。

2.CREATE INDEX

CREATE INDEX可对表增加普通索引或UNIQUE索引。

CREATE INDEX index_name ON table_name (column_list)

CREATE UNIQUE INDEX index_name ON table_name (column_list)

table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名不可选。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引。

3.索引类型

在创建索引时,可以规定索引能否包含重复值。如果不包含,则索引应该创建为PRIMARY KEY或UNIQUE索引。对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。

PRIMARY KEY索引和UNIQUE索引非常类似。事实上,PRIMARY KEY索引仅是一个具有名称PRIMARY的UNIQUE索引。这表示一个表只能包含一个PRIMARY KEY,因为一个表中不可能具有两个同名的索引。

下面的SQL语句对students表在sid上添加PRIMARY KEY索引。

ALTER TABLE students ADD PRIMARY KEY (sid)

删除索引

可利用ALTER TABLE或DROP INDEX语句来删除索引。类似于CREATE INDEX语句,DROP INDEX可以在ALTER TABLE内部作为一条语句处理,语法如下。

DROP INDEX index_name ON talbe_name

ALTER TABLE table_name DROP INDEX index_name

ALTER TABLE table_name DROP PRIMARY KEY

其中,前两条语句是等价的,删除掉table_name中的索引index_name。

第3条语句只在删除PRIMARY KEY索引时使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。

如果从表中删除了某列,则索引会受到影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。

 

2. 索引理解

[转] http://terry831010.blog.163.com/blog/static/69161171201382011498834/

项目中,发现经常有人弄错索引,不是没有命中索引,就是建了一堆多余的索引浪费空间。 对于索引,只有正确理解后才能正确使用。
   以下几个问题,如果能快速回答,请略过。
   表a, 字段:  id(自增id),user(用户名),pass(密码),type(类型 0,1),
   索引: user + pass 建立联合索引 ,user唯一索引,pass普通索引 ,type 普通索引
1 、SQL:  SELECT   *   FROM   a  WHERE user = 'terry'  AND PASS = 'nndhsbd1243AC' 
    会命中哪个索引? 
2、SQL:  SELECT   *   FROM   a  WHERE user = 'terry'  OR   user= 'frank' 
   会命中哪个索引?  

3、SQL:  SELECT   *   FROM   a  WHERE user = 'terry'
   会命中哪个索引?  

4、SQL:  SELECT   *   FROM   a  WHERE pass = 'ssssssssss'    会命中哪个索引?

5、哪些索引是多余的

6、SELECT   *   FROM   a  WHERE user = 'terry'  OR   user= 'frank'   与 SELECT   user,pass  FROM   a  WHERE user = 'terry'  OR   user= 'frank'  哪个快,为什么?

7、SELECT * FROM a WHERE length(user) = 3 能命中索引吗?

1、user+pass的联合索引,2、不能命中任何索引,3、user唯一索引   4、不能命中任何索引   5、user唯一索引 、type索引可以删除
6、后者更快,因为符合索引覆盖,减少了IO .  7 不能。索引列需要隔离
为什么?
索引就是排序,目前的计算机技术和数学理论还不支持一次同时按照两个关键字进行排序,即使是联合索引,也是先按照最左边的关键字先排,然后在左边的关键字排序基础上再对其他的关键字排序,是一个多次排序的结果。 所以,单表查询,
一次最多只能命中一个索引,并且索引必须遵守最左前缀 。  可以想象字典的拼音目录,他是典型的索引,先按照首字母,然后按次字母排序。如果你知道首字母可以很快查询到,但是如果只知道最后一个字母,你仍然需要遍历全表。这就是最左前缀的通俗理论。于是基于索引的结构和最左前缀,像 OR , like '%%'  ,都是不能命中索引的,而 like 'aa%'则是可以命中的。
  无论是innodb还是myisam,索引只记录被排序的行的主键或者地址,其他的字段还是需要二次查询,因此,如果查询的字段刚好只是包含在索引中,那么索引覆盖将是高效的。
 
尽然是排序,那么需要考虑选择性,如果所有的数据都一样,或者基本一样,那么就没有排序的必要了。像例子中的type只有1或者0,选择性是0.5,极低的样纸,所以可以忽视,即使建立了,也是浪费空间,mysql在查询的时候也会选择丢弃。
  类似最左前缀,查询索引的时候,如果列被应用了函数,那么在查询的时候,是不会用到索引的。道理很简单,函数运算已经改变了列的内容,而原始的索引是对列内容全量排序的。
   综上所述,索引的几个知识点:最左前缀,索引覆盖,索引选择性,列隔离在建立和使用索引的时候需要格外注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值