sql - 优化我的 mysql 查询以使用索引进行排序

标签 sql mysql optimization query-optimization

我需要你的帮助来优化下面的查询。假设我们有一个用于文章的 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, 40MySQL 将不必扫描整个索引。它只会选择前 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/

相关文章:

MySQL 将行值合并为单行

mysql - 检查任一列是否为空

mysql - 使用 Wampserver 安装 WordPress 时出现““Can’ t 选择数据库”错误

java - 如何查看 HotSpot 优化后生成的代码?

sql - 多个 ID 的公差范围内的最接近值

java - 从单个 ibatis 查询返回多种类型

javascript - 添加行并运行多个 mySQL 查询

python - 使用 django 查询的内置方法

c++ - 将预先分配的 vector <complex<double>>重新用作两倍长度的 vector <double>

sql - 如何将别名添加到 group by 子句