【问题标题】:MySQL Slow query: count articles, group by category, any way to optimize?MySQL慢查询:统计文章,按类别分组,有什么办法优化?
【发布时间】:2012-05-09 05:02:39
【问题描述】:

有没有办法优化这个查询?耗时超过 2.5 秒。

SELECT articles.categories_id,
    COUNT(articles.id) AS count
FROM articles
WHERE articles.created >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
GROUP BY articles.categories_id
ORDER BY count DESC

CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(11) NOT NULL,
  `categories_id` int(11) NOT NULL,
  `feeds_id` int(11) NOT NULL DEFAULT '0',
  `users_id` int(11) NOT NULL DEFAULT '1',
  `title` varchar(255) CHARACTER SET utf8 NOT NULL,
  `sefriendly` varchar(255) CHARACTER SET utf8 NOT NULL,
  `body` text CHARACTER SET utf8,
  `source` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
  `created` datetime NOT NULL,
  `edited` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `fingerprint` varchar(32) CHARACTER SET utf8 NOT NULL,
  `type` int(1) NOT NULL DEFAULT '1' COMMENT '1 => Feed fetched article\n2 => User submitted article',
  `description` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
  `keywords` text CHARACTER SET utf8,
  `status` int(1) NOT NULL DEFAULT '0' COMMENT '0 => Passive\n1 => Active\n2 => Pending',
  PRIMARY KEY (`id`),
  KEY `categories_id` (`categories_id`) USING BTREE,
  KEY `feeds_id` (`feeds_id`) USING BTREE,
  KEY `users_id` (`users_id`) USING BTREE,
  KEY `fingerprint` (`fingerprint`) USING BTREE,
  KEY `title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci ROW_FORMAT=COMPACT;

我已经使用缓存了,所以在代码方面没有问题。

这是解释sql的结果:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  articles    index   NULL    categories_id   4   NULL    120411  Using where; Using temporary; Using file sort

谢谢。

【问题讨论】:

    标签: mysql query-optimization explain


    【解决方案1】:

    您可以通过在created 上添加索引来改进。这将有助于为您的 WHERE 子句提供服务:

    WHERE articles.created >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
    

    (created, categories_id) 上创建一个覆盖索引可能会更有利,这样查询所需的所有数据都可以在索引中使用。

    请注意,此查询不需要 id 的值,因为 COUNT 只关心值是 NULL 还是 NOT NULL,但 id 在表定义中被定义为 NOT NULL。通过使用COUNT(*)COUNT(1) 而不是COUNT(id) 来明确这一点可能是一个好主意,因为这样可以保证给出相同的结果。但我希望 MySQL 足够智能,可以自动为您进行优化。

    我认为您不能避免文件排序,因为您正在对聚合结果进行排序,而这无法被索引。

    【讨论】:

    • 只在创建时创建和索引就可以了。非常感谢。
    猜你喜欢
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    相关资源
    最近更新 更多