【问题标题】:Why isn't mySQL using my index in my test query?为什么 mySQL 不在我的测试查询中使用我的索引?
【发布时间】:2011-06-09 15:05:47
【问题描述】:

我有一个简单的 mysql 表,我想用它来进行日常统计跟踪。在将一些信息放入其中并测试我将在其上使用的示例查询之后,它没有使用我的索引!我不知道为什么。

我尝试放入更多测试数据 - 200 行。我还尝试将 select * 更改为选择 created,value1。没有骰子。

mysql> show create table stat_general\G
*************************** 1. row ***************************
       Table: stat_general
Create Table: CREATE TABLE `stat_general` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `nameid` smallint(6) NOT NULL,
  `value1` int(11) NOT NULL,
  `value2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `created` (`created`,`nameid`,`value2`)
) ENGINE=MyISAM AUTO_INCREMENT=49 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select * from stat_general;
+----+---------------------+--------+--------+--------+
| id | created             | nameid | value1 | value2 |
+----+---------------------+--------+--------+--------+
|  1 | 2011-06-09 09:43:41 |      1 | 511803 |   NULL |
|  2 | 2011-06-09 09:43:41 |      2 |     44 |   NULL |
|  3 | 2011-06-09 09:43:41 |      3 |   9128 |   NULL |
|  4 | 2011-06-09 09:43:41 |      4 |    219 |   NULL |
|  5 | 2011-06-09 09:43:41 |      5 |      0 |   NULL |
|  6 | 2011-06-09 09:43:41 |      6 |      0 |   NULL |
|  7 | 2011-06-09 09:43:41 |      7 |      0 |   NULL |
|  8 | 2011-06-09 09:43:41 |      8 |      0 |   NULL |
|  9 | 2011-06-09 09:43:41 |      9 |      0 |   NULL |
| 10 | 2011-06-09 09:43:41 |     10 |    140 |   NULL |
| 11 | 2011-06-09 09:43:41 |     11 |      0 |   NULL |
| 12 | 2011-06-09 09:43:41 |     12 |    146 |   NULL |
| 13 | 2011-06-09 09:43:41 |     13 |      0 |   NULL |
| 14 | 2011-06-09 09:43:41 |     14 |      1 |   NULL |
| 15 | 2011-06-09 09:43:41 |     15 |   8981 |   NULL |
| 16 | 2011-06-09 09:43:41 |     16 |      1 |   -127 |
| 17 | 2011-06-09 09:43:41 |     16 |      2 |     -2 |
| 18 | 2011-06-09 09:43:41 |     16 |    939 |     -1 |
| 19 | 2011-06-09 09:43:41 |     16 |    146 |      1 |
| 20 | 2011-06-09 09:43:41 |     16 |   8011 |      3 |
| 21 | 2011-06-09 09:43:41 |     16 |     28 |    127 |
| 22 | 2011-06-09 09:43:41 |     16 |      1 |    128 |
| 23 | 2011-06-09 09:43:41 |     17 |    146 |      1 |
| 24 | 2011-06-09 09:43:41 |     18 |    146 |      1 |
| 25 | 2011-06-09 09:44:08 |      1 | 511803 |   NULL |
| 26 | 2011-06-09 09:44:08 |      2 |     44 |   NULL |
| 27 | 2011-06-09 09:44:08 |      3 |   9128 |   NULL |
| 28 | 2011-06-09 09:44:08 |      4 |    219 |   NULL |
| 29 | 2011-06-09 09:44:08 |      5 |      0 |   NULL |
| 30 | 2011-06-09 09:44:08 |      6 |      0 |   NULL |
| 31 | 2011-06-09 09:44:08 |      7 |      0 |   NULL |
| 32 | 2011-06-09 09:44:08 |      8 |      0 |   NULL |
| 33 | 2011-06-09 09:44:08 |      9 |      0 |   NULL |
| 34 | 2011-06-09 09:44:08 |     10 |    140 |   NULL |
| 35 | 2011-06-09 09:44:08 |     11 |      0 |   NULL |
| 36 | 2011-06-09 09:44:08 |     12 |    146 |   NULL |
| 37 | 2011-06-09 09:44:08 |     13 |      0 |   NULL |
| 38 | 2011-06-09 09:44:08 |     14 |      1 |   NULL |
| 39 | 2011-06-09 09:44:08 |     15 |   8981 |   NULL |
| 40 | 2011-06-09 09:44:08 |     16 |      1 |   -127 |
| 41 | 2011-06-09 09:44:08 |     16 |      2 |     -2 |
| 42 | 2011-06-09 09:44:08 |     16 |    939 |     -1 |
| 43 | 2011-06-09 09:44:08 |     16 |    146 |      1 |
| 44 | 2011-06-09 09:44:08 |     16 |   8011 |      3 |
| 45 | 2011-06-09 09:44:08 |     16 |     28 |    127 |
| 46 | 2011-06-09 09:44:08 |     16 |      1 |    128 |
| 47 | 2011-06-09 09:44:08 |     17 |    146 |      1 |
| 48 | 2011-06-09 09:44:08 |     18 |    146 |      1 |
+----+---------------------+--------+--------+--------+
48 rows in set (0.00 sec)

mysql> select * from stat_general where created>'2011-06-09 9:44' AND nameid=1;
+----+---------------------+--------+--------+--------+
| id | created             | nameid | value1 | value2 |
+----+---------------------+--------+--------+--------+
| 25 | 2011-06-09 09:44:08 |      1 | 511803 |   NULL |
+----+---------------------+--------+--------+--------+
1 row in set (0.00 sec)

mysql> explain select * from stat_general where created>'2011-06-09 9:44' AND nameid=1;
+----+-------------+--------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table        | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+--------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | stat_general | ALL  | created       | NULL | NULL    | NULL |   48 | Using where |
+----+-------------+--------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

【问题讨论】:

    标签: mysql indexing database-schema


    【解决方案1】:

    两个原因:

    首先,您的桌子太小了。有了这几行,打开整个表并逐个过滤行而不考虑查询会更快。

    接下来,即使您有更多具有非常相似数据的行,您当前的索引也不够有选择性。在这种情况下,随机打开磁盘页面是不值得的;按顺序打开它们并过滤掉无效行会更快。

    【讨论】:

    • 所以我猜这只是我的测试数据很差的一个函数。在现实世界中,我每天都会有一次 nameid=1-18 的行,可能是一年的数据。我可能会提取过去 3 周的特定统计数据。
    • 在这种情况下,它将使用索引,除非它正在检索大量行。
    【解决方案2】:

    只是为了笑...您的查询主要基于给定的“nameID”还是“Created”。如果 NameID(即:特定人发生了什么),我会将索引和标准更改为

    KEY `byName` ( `nameid`,`created`,`value2`)
    

    然后您的查询...

    where nameid = 1 AND created > '2011-06-09 9:44'
    

    我不是肯定的,但如果标准是匹配索引的自然顺序,它可能会直接利用它而不是猜测索引......(特别是对于更大的数据集)......否则@Denis 是对的只是查询数据页,因为它太小了,而且不管它应该使用哪个索引,都会遍历它们。

    【讨论】:

    • 放入更多数据确实解决了这个问题。但重新排列索引是个好主意。我的查询中总是有一个 nameid=X,但并不总是一个创建的(如果我想从所有时间提取数据怎么办?)。我将重新排列索引。谢谢!
    猜你喜欢
    • 2017-02-15
    • 2011-11-09
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多