数据库相关(1)-- Mysql索引

M ysql索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这本书1000页,有500也是目录,它当然效率低,目录是要占纸张的,而索引是要占磁盘空间的。

Mysql常见索引有:主键索引、唯一索引、普通索引、全文索引、组合索引

PRIMARY KEY(主键索引) 

    CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) )

    ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )

UNIQUE(唯一索引)    

    CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表)

    ALTER TABLE `table_name` ADD UNIQUE (`column`)

INDEX(普通索引)    

    创建索引,CREATE INDEX <索引的名字> ON tablename (列的列表);

    修改索引,ALTER TABLE `table_name` ADD INDEX index_name ( `column` )

    创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) )

FULLTEXT(全文索引)     

    ALTER TABLE `table_name` ADD FULLTEXT ( `column` )

组合索引

    ALTER TABLE `table_name` ADD INDEX index_name ( `column1`,`column2`, `column3` )


Mysql各种索引区别:

普通索引:最基本的索引,没有任何限制。

唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。

主键索引:它是一种特殊的唯一索引,不允许有空值。

全文索引:仅可用于MyISAM表,针对较大的数据,生成全文索引很耗时好空间。

组合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。


讲下你项目里做的数据库索引优化,如何去分析一条语句的执行性能,explain语句你会关注哪些字段

索引优化策略:

 *最左前缀匹配原则,上面讲到了

 *主键外检一定要建索引

 *对 where,on,group by,order by 中出现的列使用索引

 *尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0。对较小的数据列使用索引,这样会使索引文件更小,同时内存中也可以装载更多的索引键

 *索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

 *为较长的字符串使用前缀索引

 *尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可,不要过多创建索引, 权衡索引个数与DML之间关系,DML也就是插入、删除数据操作。这里需要权衡一个问题,建立索引的目的是为了提高查询效率的,但建立的索引过多,会影响插入、删除数据的速度,因为我们修改的表数据,索引也需要进行调整重建

 *对于like查询,”%”不要放在前面。

   SELECT * FROM houdunwang WHERE uname LIKE '后盾%' -- 走索引

   SELECT *FROM houdunwang WHERE uname LIKE  '%后盾%' -- 不走索引

 *查询where条件数据类型不匹配也无法使用索引

 *字符串与数字比较不使用索引;

CREATE TABLE a(a char(10));

EXPLAIN SELECT * FROM a WHERE a="1" – 走索引

EXPLAIN SELECT * FROM a WHERE a=1 – 不走索引

正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因


Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句。

Explain语法:

EXPLAIN

tbl_name或:EXPLAIN[EXTENDED] SELECT select_options

前者可以得出一个表的字段结构等等,后者主要是给出相关的一些索引信息,而今天要讲述的重点是后者。

例如:

EXPLAIN

  SELECT sum(amount)

FROM customer a, payment b

  WHERE1 = 1

AND a.customer_id = b.customer_id

AND a.email = '[email protected]';

执行结果:

下面对各个属性进行了解:

1、id:这是SELECT的查询序列号。每个 SELECT 都会自动分配一个唯一的标识符。

2、select_type:select_type就是select的类型,可以有以下几种:

    SIMPLE:简单SELECT(不使用UNION或子查询等)

    PRIMARY:最外面的SELECT

    UNION:UNION中的第二个或后面的SELECT语句

    DEPENDENT UNION:UNION中的第二个或后面的SELECT语句,取决于外面的查询

    UNION RESULT:UNION的结果。

    SUBQUERY:子查询中的第一个SELECT

    DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询

    DERIVED:导出表的SELECT(FROM子句的子查询)

3、table:显示这一行的数据是关于哪张表的实际的表名(如select * from customer;) 或表的别名 (如 select * from customer a);

4、type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。通过 type 字段, 我们判断此次查询是 全表扫描 还是 索引扫描等。

system > const > eq_ref > ref > fulltext >ref_or_null > index_merge > unique_subquery > index_subquery >range > index > ALL

一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

    ● all: 意味着从表的第1行,往后逐行做全表扫描,运气不好扫描到最后一行。

    ● index:表示全索引扫描(full index scan),和 ALL 类型类似,只不过 ALL 类型是全表扫描, 而 index 类型则仅仅扫描所有的索引, 而不扫描数据。比all性能稍好一点,通俗的说: all 扫描所有的数据行,相当于data_all index 扫描所有的索引节点,相当于index_all。注:all是沿着磁盘扫描,index是沿着索引扫描。例如:EXPLAIN SELECT name FROM user_info。上面的例子中, 我们查询的 name 字段恰好是一个索引, 因此我们直接从索引中获取数据就可以满足查询的需求了, 而不需要查询表中的数据. 因此这样的情况下, type 的值是 index, 并且 Extra 的值是Using Index。

    ● range: 意思是查询时,能根据索引做范围的扫描。表示使用索引范围查询,通过索引字段范围获取表中部分数据记录。这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中。当 type 是 range 时, 那么 EXPLAIN 输出的 ref 字段为 NULL, 并且 key_len 字段是此次查询中使用到的索引的最长的那个。例如,EXPLAIN SELECT * FROM user_info WHERE id BETWEEN 2 AND 8。

    ● index_subquery 在子查询中,基于除唯一索引之外的索引进行扫描;

    ● unique_subquery在子查询中,基于唯一索引进行扫描,类似于EQ_REF;

    ● index_merge 多重范围扫描。两表连接的每个表的连接字段上均有索引存在且索引有序,结果合并在一起。适用于作集合的并、交操作。

    ● ref_or_null 类似REF,只是搜索条件包括:连接字段的值可以为NULL的情况,比如where col = 2 or col is null

    ● fulltext 全文索引

    ● ref 此类型通常出现在多表的 join 查询。针对于非唯一或非主键索引,或者是使用了最左前缀 规则索引的查询(也是范围区间,不过比range更加精确)。例如,EXPLAIN SELECT * FROM user_info, order_info WHERE user_info.id = order_info.user_id AND order_info.user_id = 5。

    ● eq_ref是指通过索引列,直接引用某1行数据(精确到一行数据中)常见于连接查询中,表示对于前表的每一个结果,都只能匹配到后表的一行结果。并且查询的比较操作通常是 =,查询效率较高。例如,EXPLAIN SELECT * FROM user_info,order_info WHERE user_info.id = order_info.user_id。

    ● const, system, null 当mysql能对查询的部分就行优化,并且转换成一个常量的时候,它就会使用这种访问类型了。比如你把一行的主键当做where条件放进去,那mysql就可以把它转换成一个常量,然后查询。例如,explain select * from user_info where id = 2。

5、possible_keys:列指出MySQL能使用哪个索引在该表中找到行

6、key:此字段是 MySQL 在当前查询时所真正使用到的索引。如果没有选择索引,键是NULL。

7、key_len:显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

8、ref:显示使用哪个列或常数与key一起从表中选择行。

9、rows:显示MySQL认为它执行查询时必须检查的行数。rows 也是一个重要的字段。

      MySQL查询优化器根据统计信息, 估算 SQL 要查找到结果集需要扫描读取的数据行数。这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好。

10、Extra:包含MySQL解决查询的详细信息,也是关键参考项之一。

你可能感兴趣的:(数据库相关(1)-- Mysql索引)