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

时间:2009-12-28 21:34:37

标签: sql mysql optimization query-optimization

我需要您的帮助来优化下面的查询。我们假设我们有一个文章的Web应用程序。该软件使用两个表;一个是文章表,第二个是用户表。文章表格包含文章创建日期,身份证,正文,标题和文章。这部分。让我们假设我们有一个名为“新闻”的部分,有一百万篇文章属于新闻部分。所以在这种情况下,如何优化以下查询:

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 ;

我尝试创建一个由“&”部分组成的索引。日期,但它不是最好的,因为如果我们有2百万条记录,其中一百万条属于一个部分,那么数据库将扫描一百万行。

6 个答案:

答案 0 :(得分:0)

在article.auther_id上添加索引。除了你已经在日期和部分添加的索引。

答案 1 :(得分:0)

通过查看查询,您似乎需要一个关于节的索引和一个日期索引(两个单独的索引)。尝试添加这些,然后查看解释计划,看看它们是否有效,或者是否有其他可能有帮助的调整。

答案 2 :(得分:0)

好的,首先使用DATE数据类型作为日期,因为这比使用VARCHAR要快得多。

其次,您只需将以下键添加到文章表的create table语法中。

KEY auther_id (auther_id),
KEY section (section),

有点无关紧要,但如果你使用的是InnoDB,你还可以将auther_id作为外键。

另外,如果您不需要使用“LIKE”,那么只需检查section="news"就会快得多。 (如果有一个有限的列表,你甚至可以使用ENUM。)

答案 3 :(得分:0)

正如其他人所说,日期,部分和auther_id的索引。根据这个:

http://www.mysqlperformanceblog.com/2008/08/22/multiple-column-index-vs-multiple-indexes/

拥有一个多列索引而不是三个独立索引可能是有益的,例如:

...
key idx_combo (auther_id, section, date)
...

在你的表定义中。

答案 4 :(得分:0)

最好的办法是根据日期/部分创建分区表。

然后创建本地分区索引,使性能更高。

答案 5 :(得分:0)

您需要在(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 s完成(立即)

这是执行计划:

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, ''