我需要你的帮助来优化下面的查询。假设我们有一个用于文章的 Web 应用程序。该软件使用两个表;一个是文章表,第二个是用户表。文章表包含文章创建的日期、id、正文、标题和部分。让我们假设我们有一个名为“新闻”的版 block ,并且有一百万篇文章属于新闻版 block 。那么在这种情况下,如何优化以下查询:
SELECT username,title FROM article,users
WHERE article.auther_id=users.id AND section LIKE 'news'
ORDER BY article.date DESC
LIMIT 0,40
表结构是:
CREATE TABLE `article` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 100 ) NOT NULL ,
`body` VARCHAR( 200 ) NOT NULL ,
`date` VARCHAR( 30 ) NOT NULL ,
`auther_id` INT NOT NULL ,
`section` VARCHAR( 30 ) NOT NULL
) ENGINE = MYISAM ;
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 30 ) NOT NULL
) ENGINE = MYISAM ;
我尝试创建一个由部分和日期组成的索引,但这不是最好的,因为如果我们有 200 万条记录,其中 100 万条记录属于一个部分,数据库将扫描 100 万行。
最佳答案
您需要在 (section, date)
上创建索引。
不要将 auther_id
作为前导列:文章将在连接中领先,并且不会对该列执行任何搜索。
因为在您的查询中有一个 LIMIT 0, 40
,MySQL
将不必扫描整个索引。它只会选择前 40
条记录。
这是一个测试脚本来检查:
CREATE TABLE `article` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 100 ) NOT NULL ,
`body` VARCHAR( 200 ) NOT NULL ,
`date` VARCHAR( 30 ) NOT NULL ,
`auther_id` INT NOT NULL ,
`section` VARCHAR( 30 ) NOT NULL
) ENGINE = MYISAM ;
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 30 ) NOT NULL
) ENGINE = MYISAM ;
INSERT
INTO article
SELECT id,
CONCAT('Title ', id),
CONCAT('Body ', id),
DATE_FORMAT('2009-12-18' - INTERVAL id MINUTE, '%Y-%m-%d %H:%i:%S'),
(id - 1) % 500 + 1,
'news'
FROM t_source;
INSERT
INTO users
SELECT id, CONCAT('Username ', id)
FROM t_source
LIMIT 500;
CREATE INDEX ix_article_section_date ON article (section, date);
SELECT username,title
FROM article
JOIN users
ON users.id = article.auther_id
WHERE section = 'news'
ORDER BY
article.date DESC
LIMIT 0, 40;
t_source
是一个包含 1,000,000
行的虚拟表。
在我的机器上,最终查询在 0.0018 秒
内完成(即时)
这是执行计划:
1, 'SIMPLE', 'article', 'range', 'ix_article_section_date', 'ix_article_section_date', '92', '', 999998, 'Using where'
1, 'SIMPLE', 'users', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'test.article.auther_id', 1, ''
关于sql - 优化我的 mysql 查询以使用索引进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1971670/