我的 MySQL 查询的正确索引

发布于 2024-12-06 14:25:29 字数 1385 浏览 0 评论 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 |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+

I have the following Table:

  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

This table has more than 5 million rows.

I've set indexes, as you can see above, but in my query no indexes are used and I don't understand why. Does anybody see my problem?

Explain:

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

Result:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悲念泪 2024-12-13 14:25:29

MySQL 无法在函数内的列上使用索引。
从 select 中删除函数 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

Remarks

  • count(*)count(namedcolumn) 更快;
  • (a=1)=> 1 如果为真,(a=1) =>如果为 false,则为 0,因此可以缩短 if(a=1,1,0)
  • 最好为聚合列添加别名,以便稍后可以通过别名来引用它们。
  • 如果添加以下索引(并删除索引 forwardtime),查询将运行得更快。 KEY fasttime (forwardTime,f_shop,toolbarUser)
  • 上一点在 InnoDB 上尤其如此,MySQL 将在可能的情况下使用覆盖索引,这意味着如果它不存在,它永远不会读取表本身来检索数据。可以在索引中找到所需的一切。

MySQL cannot use an index on a column inside a function.
Remove the function date() from your select and MySQL will use the index.

You can do this by changing your column definition of forwardtime to DATE
Or you can change the query like so

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

Remarks

  • count(*) is faster than count(namedcolumn);
  • (a=1) => 1 if true, (a=1) => 0 if false, so the if(a=1,1,0) can be shortened;
  • It's a good idea to alias your aggregate columns, so you can refer to them by their alias later.
  • If you add the following index (and remove index forwardtime), you query will run even faster. KEY fasttime (forwardTime,f_shop,toolbarUser)
  • The previous point is especially true on InnoDB where MySQL will use a covering index if possible, which means that it will never read the table itself to retrieve the data if it can find all it needs in the index.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文