在哪些情况下,我应该为多列创建一个索引,而不是为每一列创建单独的索引?
3 回答
如果您的查询条件包含多列。如果将所有列形式条件添加到索引。您将加快执行速度。使用EXPLAIN
命令检查添加索引前后的执行计划。当然,不要添加太多列,尤其是不同类型的列,因为添加索引可能没有任何好处。
它不必是非此即彼的情况。假设您有一个 ORDERS 表:
orderid integer,
orderdate date,
etc...
和一个 ORDERDETAIL 表
orderid integer,
lineno integer,
productID integer,
etc...
您可能需要一个索引,orderdetail.orderid
因为您将一直对其进行查找,并且 DBMS 将使用它来验证您的外键查找时的引用完整性orders
。然而,你可能最终会做很多看起来像这样的选择:
select *
from orderdetail
where orderid=?
order by lineno
在这种情况下,索引orderdetail.orderid,orderdetail.lineno
将是有益的。
组合索引将有助于大多数场景。如果你有一张像下面这样的表格。
考虑下表。
用户
+-----------+--------------+------+-----+---------+-------+
| 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
column 创建索引。
解释为时间戳列创建索引后的输出。
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 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 |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
它仍然没有作为 range query 执行。因为我们只索引了TIMESTAMP
column 。我们想创建一个组合索引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 |
+----+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
现在,它作为范围查询执行并查看检查的行数,它只扫描超过给定时间标准。组合索引将有助于大型表。