索引是否依赖于所选列?

时间:2013-03-20 10:33:27

标签: mysql

我正在根据时间执行大多数查询。所以我为创建的时间创建了索引。但是,索引只能起作用,如果我只选择索引列。 mysql索引是否依赖于所选列?

我对索引的假设

我认为索引就像电话词典索引页面。例如:如果我想找到“马克”。索引页面显示目录中的哪个页面字符“M”。我认为和mysql一样。

表格

+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| ID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Name         | varchar(100) | YES  |     | NULL    |                |
| OPERATION    | varchar(100) | YES  |     | NULL    |                |
| PID         | int(11)      | YES  |     | NULL    |                |
| CREATED_TIME | bigint(20)   | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+

索引在桌面上。

    +-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| IndexTest |          0 | PRIMARY  |            1 | ID           | A         |       10261 |     NULL | NULL   |      | BTREE      |         |               |
| IndexTest |          1 | t_dx     |            1 | CREATED_TIME | A         |         410 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

查询使用索引:

   explain select * from IndexTest where ID < 5;
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | IndexTest | range | PRIMARY       | PRIMARY | 4       | NULL |    4 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+



  explain select CREATED_TIME from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
    +----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | IndexTest | range | t_dx          | t_dx | 9       | NULL | 5248 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+

查询未使用索引

    explain select count(distinct(PID)) from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | IndexTest | ALL  | t_dx          | NULL | NULL    | NULL | 10261 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+


    explain select PID from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | IndexTest | ALL  | t_dx          | NULL | NULL    | NULL | 10261 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+

5 个答案:

答案 0 :(得分:5)

简答:否。

是否使用索引取决于WHERE子句,JOIN等中的表达,而不取决于您选择的列。

但没有例外的规则(或实际上是一长串的那些):

答案很长:通常不是

MySQL Optimizer使用了许多因素来确定它是否应该使用索引。

如果......

,优化器可能会决定忽略索引
  • 另一个(否则是非最佳的)使其无法全部访问表格数据
  • 它无法理解表达式是常量
  • 其估计表明无论如何都将返回完整的表格
  • 如果使用它将导致创建临时文件
  • ......还有很多其他原因,其中一些似乎没有记录在案

有时候,所述优化器做出的选择是......呃...让我们称之为次优。那么你在那些情况下做了什么?

  • 您可以通过OPTIMIZE TABLE和/或ANALYZE TABLE来帮助优化工具。这很容易做到,有时也有帮助。
  • 您可以使用USE INDEX(indexname)FORCE INDEX(indexname)语法
  • 使用某个索引
  • 您可以使用IGNORE INDEX(indexname)语法
  • 忽略某个索引

有关MySQL文档网站上Index HintsOptimize TableAnalyze Table的详细信息。

答案 1 :(得分:4)

实际上,选择列时没有区别。索引用于查找,这意味着可以非常快速地减少需要检索的记录数。这使得它通常在以下情况下很有用:你有联接,你有条件。索引也有助于订购。

使用where条件的索引也可以大大加快更新和删除。

举个例子:

table: id int pk ai, col1 ... indexed, col2 ...
select * from table -> does not use a index
select id from table where col1 = something -> uses the col1 index although it is not selected.

查看第二个查询,mysql在索引中执行查找,查找记录,然后在这种情况下停止并传递(id和col1都有索引和id恰好是pk,所以不需要辅助查找)

在这种情况下情况稍有变化:

select col2 from table where col1 = something

这将在内部进行2次查找:1表示条件,1表示pk用于传递col2数据。请注意,您不需要选择col1列来使用索引。

回到您的查询,问题在于:UNIX_TIMESTAMP(CURRENT_DATE())* 1000; 如果删除它,您的索引将用于查找。

答案 2 :(得分:3)

  

mysql索引是否依赖于所选列?

是的,绝对。

example

  

如果列不形成最左边的列,则MySQL无法使用索引执行查找   索引的前缀。假设您在此处显示SELECT语句:

SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
     

如果(col1, col2, col3)上存在索引,则只有前两个查询使用索引。   第三个和第四个查询确实涉及索引列,但(col2)(col2, col3)   不是(col1, col2, col3)的最左前缀。

请仔细阅读the extensive documentation

答案 3 :(得分:2)

对于mysql查询,答案是肯定的,但不是全部

查询:

  

解释select * from IndexTest,其中ID&lt; 5;

如果你使用表的主键innodb,那么

使用表簇索引,所以它使用primary作为查询

第二个问题:

  

从IndexTest中选择CREATED_TIME,其中CREATED_TIME&gt;   UNIX_TIMESTAMP(CURRENT_DATE())* 1000;

这个只是获取索引列,mysql不需要从表中获取数据而只是索引,所以你的解释结果得到了“使用索引”

查询:

  

从IndexTest中选择count(distinct(PID)),其中CREATED_TIME&gt;   UNIX_TIMESTAMP(CURRENT_DATE())* 1000;

看起来像这样

  

从IndexTest中选择PID   CREATE_TIME&gt; UNIX_TIMESTAMP(CURRENT_DATE())*按PID分组1000

mysql也可以使用索引从数据库中获取数据,但是mysql认为这个查询不需要使用索引来获取数据,因为where条件过滤器, mysql认为使用索引获取数据比扫描所有表格,您也可以使用force index

您上次查询的原因相同

跳跃这个答案可以帮到你

答案 4 :(得分:0)

索引有助于加快搜索特定列和关联数据的速度,而不是表格数据。因此,您必须包含索引列以加快select