4

I am executing most of the queries based on the time. So i created index for the created time. But , The index only works , If I select the indexed columns only. Is mysql index is dependant the selected columns?.

My Assumption On Index

I thought index is like a telephone dictionary index page. Ex: If i want to find "Mark" . Index page shows which page character "M" starts in the directory. I think as same as the mysql works.

Table

+--------------+--------------+------+-----+---------+----------------+
| 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    |                |
+--------------+--------------+------+-----+---------+----------------+

Indexes On the table.

    +-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| 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      |         |               |
+-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

Queries Using Indexes:

   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 |
+----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+

Queries Not using Indexes

    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 |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
4

5 回答 5

6

简短的回答:没有。

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

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

长答案:通常不会

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

优化器可能会决定忽略索引,如果...

  • 另一个(否则不是最佳的)将其完全从访问表数据中保存下来
  • 它无法理解表达式是常量
  • 它的估计表明无论如何它都会返回完整的表格
  • 如果它的使用会导致创建一个临时文件
  • ...以及大量其他原因,其中一些似乎没有记录在任何地方

有时,所述优化器所做的选择是……呃……让我们称它们为次优。现在在这些情况下你会怎么做?

  • 您可以通过执行OPTIMIZE TABLEand/or来帮助优化器ANALYZE TABLE。这很容易做到,而且有时会有所帮助。
  • USE INDEX(indexname)您可以使用orFORCE INDEX(indexname)语法使其使用某个索引
  • IGNORE INDEX(indexname)您可以使用语法使其忽略某个索引

MySQL 文档网站上有关索引提示优化表分析表的更多详细信息。

于 2013-03-29T16:39:42.560 回答
4

实际上,您是否选择列都没有区别。索引用于查找,这意味着快速减少您需要检索的记录数。这使得它通常在以下情况下很有用:你有连接,你有 where 条件。索引也有助于排序。

使用 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; 如果您删除它,您的索引将用于查找。

于 2013-03-31T02:50:35.240 回答
3

mysql索引是否依赖于选定的列?

是的,一点没错。

例如:_

如果列不构成索引的最左前缀,则 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).

阅读大量文档

于 2013-03-20T10:37:38.693 回答
2

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

查询:

解释 select * from IndexTest where ID < 5;

如果你使用innodb,它的表的主键使用表簇索引,所以它使用primary进行查询

第二个查询:

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

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

查询:

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

它看起来像这样

从 IndexTest 中选择 PID,其中 CREATE_TIME>UNIX_TIMESTAMP(CURRENT_DATE())*1000 按 PID 分组

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

您上次查询的相同原因

跳这个答案可以帮助你

于 2013-04-01T02:29:37.197 回答
0

索引有助于加快对特定列和相关数据而不是表数据的搜索。所以你必须包括索引列来加速select

于 2013-03-20T10:39:47.387 回答