我有一个约1百万条的mySQL DB。
我运行查询:
SELECT a.id as aid, a.title as atitle, a.slug, summary,
a.link as alink, author, published, image, a.cat as acat,
a.rss as arss, a.site as asite
FROM articles a
ORDER BY published DESC
LIMIT 616150, 50;
大约需要5分钟或更长时间。
我的表和索引:
CREATE TABLE IF NOT EXISTS `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`slug` varchar(255) NOT NULL,
`summary` text NOT NULL,
`link` text NOT NULL,
`author` varchar(255) NOT NULL,
`published` datetime NOT NULL,
`image` text NOT NULL,
`cat` int(11) NOT NULL,
`rss` int(11) NOT NULL,
`site` int(11) NOT NULL,
`bitly` varchar(255) NOT NULL,
`checked` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`),
KEY `cat` (`cat`),
KEY `published` (`published`),
KEY `site` (`site`),
KEY `rss` (`rss`),
KEY `checked` (`checked`),
KEY `id_publ_index` (`id`,`published`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1230234;
解释说:
mysql> EXPLAIN EXTENDED SELECT a.id as aid, a.title as atitle, a.slug, summary, a.link as alink, author, published, image, a.cat as acat, a.rss as arss, a.site as asite FROM articles a ORDER BY published DESC LIMIT 616150, 50; +----+-------------+-------+-------+---------------+-----------+---------+------+--------+----------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+-------+---------------+-----------+---------+------+--------+----------+-------+ | 1 | SIMPLE | a | index | NULL | published | 8 | NULL | 616200 | 152.94 | | +----+-------------+-------+-------+---------------+-----------+---------+------+--------+----------+-------+ 1 row in set, 1 warning (0.46 sec)
有关如何优化此查询的任何提示?为什么mySQL需要读取所有616200行,而不仅仅是要求读取的50行?
感谢您的时间。
答案 0 :(得分:1)
您看到使用published
密钥的原因是因为您正在订购该密钥。这个查询需要多久运行一次?
你可以做一件简单的事情来帮助这个查询运行得更快,更快:
更好地利用您的published
密钥。使用WHERE
定义要从表格中检索的日期范围。
您现在正在阅读616,200行表的原因是因为您没有使用索引来限制范围。 MySQL需要使用完整索引来:
如果可能,您应该以不同的方式过滤数据库的结果。将结果更改为基于WHERE(更有效地使用索引)将是最快捷的方式。
例如:
SELECT a.id as aid, a.title as atitle, a.slug, summary,
a.link as alink, author, published, image, a.cat as acat,
a.rss as arss, a.site as asite
FROM articles a
WHERE published > '2010-01-01'
ORDER BY published DESC
LIMIT 6150, 50;
令人遗憾的是,ORDER BY和LIMIT不能很好地扩展,你很快就会失去速度。 (例如,将您的限制更改为0, 50
,然后更改为900000, 50
并查看速度是如何受到影响的,因此向WHERE添加更多信息将有助于您的查询更快。
修改强>
我无法知道按日期显示的内容,因此无法放置在哪里。此外,此查询在新闻聚合器上运行,每隔一秒收集一次新闻。这个限制是我可以创建分页结果。
因为您正在插入新帖子,所以LIMIT语句将导致新闻项目在用户正在浏览页面时跳转。例如,如果我在第一页和第三页上添加了“下一步”,那么当我点击“下一页”时,我会看到上一页的最后三项。
为了获得最佳用户体验,您应尝试以某种方式将最后看到的新闻项的ID或上次看到的新闻项的日期添加到分页中。这可以通过会话或部分查询URL来完成,但它可以让您更好地使用索引。
我理解为什么会有限制 - 这就是如何在一定数量的网页被点击后解决查询问题的速度。
要有效地解决速度问题,您需要更好地使用索引,而不是依赖“LIMIT”作为您唯一的分页方法。 LIMIT是惊人的,是的,但它没有针对您尝试执行此操作的方式检索记录进行优化,因为您需要按日期排序。
即使你说“我无法知道按日期显示什么”(至少目前......),你的应用程序必须有一种方法来限制从数据库中提取的内容。同样,Facebook不需要浏览网站每个成员的个人帖子,只是为了在Facebook墙上显示结果。您需要了解如何提高效率。