我正在根据时间执行大多数查询。所以我为创建的时间创建了索引。但是,索引只能起作用,如果我只选择索引列。 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 |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
答案 0 :(得分:5)
简答:否。
是否使用索引取决于WHERE
子句,JOIN
等中的表达,而不取决于您选择的列。
但没有例外的规则(或实际上是一长串的那些):
答案很长:通常不是
MySQL Optimizer使用了许多因素来确定它是否应该使用索引。
如果......
,优化器可能会决定忽略索引有时候,所述优化器做出的选择是......呃...让我们称之为次优。那么你在那些情况下做了什么?
OPTIMIZE TABLE
和/或ANALYZE TABLE
来帮助优化工具。这很容易做到,有时也有帮助。 USE INDEX(indexname)
或FORCE INDEX(indexname)
语法IGNORE INDEX(indexname)
语法有关MySQL文档网站上Index Hints,Optimize Table和Analyze 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索引是否依赖于所选列?
是的,绝对。
如果列不形成最左边的列,则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)
的最左前缀。
答案 3 :(得分:2)
对于mysql查询,答案是肯定的,但不是全部
查询:
如果你使用表的主键innodb,那么解释select * from IndexTest,其中ID&lt; 5;
使用表簇索引,所以它使用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;
看起来像这样
mysql也可以使用索引从数据库中获取数据,但是mysql认为这个查询不需要使用索引来获取数据,因为where条件过滤器, mysql认为使用索引获取数据比扫描所有表格,您也可以使用从IndexTest中选择PID CREATE_TIME&gt; UNIX_TIMESTAMP(CURRENT_DATE())*按PID分组1000
force index
您上次查询的原因相同
跳跃这个答案可以帮到你
答案 4 :(得分:0)
索引有助于加快搜索特定列和关联数据的速度,而不是表格数据。因此,您必须包含索引列以加快select
。