我需要您的帮助来优化下面的查询。我们假设我们有一个文章的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百万条记录,其中一百万条属于一个部分,那么数据库将扫描一百万行。
答案 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, 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 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, ''