2015-02-07 41 views
0

我有一个客户希望我为他的网站做一个后端。他需要一张表格来显示所有带分页的文件。如何优化排序和限制?

CREATE TABLE `content_files` (
    `id` varchar(16) NOT NULL, 
    `owner` varchar(16) DEFAULT NULL, 
    `location` varchar(16) NOT NULL, 
    `parent` varchar(16) DEFAULT NULL, 
    `date` int(11) NOT NULL, 
    `filename` varchar(256) NOT NULL, 
    `username` varchar(64) NOT NULL, 
    `email` varchar(256) NOT NULL, 
    `ip` varchar(15) NOT NULL, 
    `json` text NOT NULL, 
    `bin` blob NOT NULL 
); 

ALTER TABLE `content_files` 
    ADD PRIMARY KEY (`id`), 
    ADD UNIQUE KEY `ID` (`id`), 
    ADD KEY `id_2` (`id`), 
    ADD KEY `date` (`date`), 
    ADD KEY `filename` (`filename`(255)), 
    ADD KEY `username` (`username`(63)), 
    ADD KEY `email` (`email`(255)), 
    ADD KEY `ip` (`ip`(14)); 

需要排序的项目是日期,文件名,用户名,电子邮件和IP。目前有65,000条记录。如果极限高,如预期的那样需要更长的时间,但是它非常长。 100秒获得第60,000条。

我只是用:

SELECT id, date, filename, username, email ip 
FROM content_files 
ORDER BY filename 
LIMIT 60000, 20 

找遍了这个问题,但是,没有任何提示似乎改善我的查询。在他的模式中是否有一些明显的错误?我怎样才能优化这个?

+0

InnoDB?显示'EXPLAIN'结果。 – 2015-02-07 18:54:10

回答

0

您正在构建一个大数据集并对其进行排序,仅丢弃60K行并显示20行。该行为可以通过所谓的延迟加入来减少。排序仍然必须发生,但它可能需要更少的内存,因此速度更快。

编辑将子查询获取到连接中。

SELECT a.id, a.date, a.filename, a.username, a.email ip 
    FROM content_files a 
    JOIN ( SELECT id 
       FROM content_files 
      ORDER BY filename 
      LIMIT 60000, 20 
     ) b ON a.id = b.id 
    ORDER BY a.filename 

这是你的伟大的排序 - 在较小的数据集上丢弃操作。然后它会查找20行所需的所有数据。

最后,如果您在(filename, id)上添加复合索引,则可以通过扫描索引来满足子查询,从而使索引更快。创建复合索引时,您可以删除filename上的索引。

你的桌子上有一堆冗余索引。 (仅在id单独三个)。清理你的索引!他们放慢更新速度。

+0

服务器正在使用的MySQL版本(5.6.2)不允许IN语句中的LIMIT。 此外,这个模式不是我自己提到的。我不确定是否明确使用了其他ID索引。在删除之前,我正在等待之前的开发人员的输入。 – 2015-02-07 20:02:31

+0

对不起'IN(LIMIT ...)'的错误。我已将其更改为“JOIN”。 – 2015-02-07 21:10:38