0

我有下表:

  CREATE TABLE `sal_forwarding` (
  `sid` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `f_shop` INT(11) NOT NULL,
  `f_offer` INT(11) DEFAULT NULL,
  .
  .
  .
  PRIMARY KEY (`sid`),
  KEY `forwardTime` (`forwardTime`,`f_shop`),
  KEY `forwardTime_2` (`forwardTime`),
  KEY `f_shop` (`f_shop`)
) ENGINE=INNODB AUTO_INCREMENT=10457068 DEFAULT CHARSET=latin1

该表有超过 500 万行。

正如您在上面看到的,我已经设置了索引,但是在我的查询中没有使用索引,我不明白为什么。有人看到我的问题吗?

解释:

EXPLAIN SELECT 
  f_shop
  , COUNT(sid)
  , SUM(IF(toolbarUser=1,1,0)) 
FROM sal_forwarding 
WHERE DATE(forwardTime) = "2011-09-01" 
GROUP BY f_shop

结果:

+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
| ID | SELECT_TYPE |     TABLE      | TYPE  | POSSIBLE_KEYS |  KEY   | KEY_LEN |  REF   |  ROWS  |    EXTRA    |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
|    |             |                |       |               |        |         |        |        |             |
| 1  | SIMPLE      | sal_forwarding | index | (NULL)        | f_shop | 4       | (NULL) | 232449 | Using where |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
4

1 回答 1

2

MySQL 不能在函数内的列上使用索引。
从您的选择中删除该函数date(),MySQL 将使用该索引。

您可以通过将列定义更改为来做到这一点,forwardtime或者DATE
您可以像这样更改查询

SELECT 
  f_shop
  , COUNT(*) as RowCount
  , SUM(toolbarUser=1) as NumberOfToolbarUsers
FROM sal_forwarding 
WHERE forwardTime BETWEEN '2011-09-01 00:00' AND '2011-09-01 23:59' 
GROUP BY f_shop

评论

  • count(*)count(namedcolumn); 快
  • (a=1) => 1 if true, (a=1) => 0 if false, 所以if(a=1,1,0)可以缩短;
  • 给聚合列起别名是个好主意,这样您以后可以通过它们的别名来引用它们。
  • 如果您添加以下索引(并删除 index forwardtime),您的查询将运行得更快。KEY fasttime (forwardTime,f_shop,toolbarUser)
  • 前一点在 InnoDB 上尤其如此,如果可能,MySQL 将使用覆盖索引,这意味着如果它可以在索引中找到所需的所有内容,它将永远不会读取表本身来检索数据。
于 2011-09-27T12:40:32.567 回答