在哪种情况下,我应该为多列创建一个索引而不是为每列创建单独的索引?

时间:2012-11-25 17:26:47

标签: mysql sql

在哪种情况下,我应该为多列创建一个索引而不是为每列创建单独的索引?

3 个答案:

答案 0 :(得分:2)

如果您的条件包含多列的查询。如果将所有列条件添加到索引中。你会加快执行速度。使用EXPLAIN命令检查添加索引之前和之后的执行计划。当然,不要添加太多列,尤其是不同类型的列,因为添加索引没有任何好处。

答案 1 :(得分:0)

综合指数将有助于大多数情况。如果你有一张如下表所示的表。

考虑下表。

用户

+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| ID        | int(11)      | YES  |     | NULL    |       |
| USER      | varchar(100) | YES  |     | NULL    |       |
| EMAIL_ID  | varchar(200) | YES  |     | NULL    |       |
| MODE      | varchar(50)  | YES  |     | NULL    |       |
| TIMESTAMP | bigint(20)   | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+

在此表中,我们正在审核用户操作,例如'SIGNIN','SIGNUP','CLOSE'。在这种情况下,我们希望从此表中更快地获取详细信息。但这将有数百万条目。

值在我的表中。

 select * from Users;
+------+----------+-----------------------+--------+---------------+
| ID   | USER     | EMAIL_ID              | MODE   | TIMESTAMP     |
+------+----------+-----------------------+--------+---------------+
|    1 | kannan   | kannanrbk.r@gmail.com | SIGNIN | 1353864896000 |
|    2 | bharathi | bharathikannan.r      | SIGNUP | 1353864934000 |
|    2 | mack     | mack@gmail.com        | SIGNIN | 1353865121000 |
|    2 | david    | david@gmail.com       | SIGNIN | 1353865130000 |
+------+----------+-----------------------+--------+---------------+

查询:

select EMAIL_ID from Users where TIMESTAMP > 1353864896000;

解释输出:

    +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | Users | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

查看解释输出

它检查表中的完整行。因为,此查询不会以range执行。我们想要为TIMESTAMP列创建索引。

在为timestamp列创建索引后解释输出。

    +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | Users | ALL  | t_dx          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

仍然没有作为范围查询执行。因为我们只为TIMESTAMP列编制了索引。我们想要创建一个TIMESTAMP,EMAIL_ID的组合索引来执行此查询作为范围一。

create index t_dx on Users(TIMESTAMP,EMAIL_ID);

在创建组合索引后解释输出。

    +----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | Users | range | t_dx          | t_dx | 9       | NULL |    3 | Using where; Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+

现在,它作为范围查询执行,并查看检查的行数,它仅扫描超过给定时间条件。组合索引将有助于大型表格。

答案 2 :(得分:0)

它不一定是一个或两个案例。假设你有一个ORDERS表:

orderid integer,
orderdate date,
etc...

和ORDERDETAIL表

orderid integer,
lineno integer,
productID integer,
etc...

您可能需要orderdetail.orderid上的索引,因为您将始终对此进行查找,并且DBMS将使用它来验证外键查找的引用完整性,返回{{1} }。但是,你可能最终会做很多选择:

orders

在这种情况下,select * from orderdetail where orderid=? order by lineno 上的索引将是有益的。