[英]Optimizing my mysql query to use index for sorting
我需要您的幫助來優化下面的查詢。 讓我們假設我們有一個用於文章的Web應用程序。 該軟件使用兩個表;一個是商品表,另一個是用戶表。 article表包含創建文章的日期,id,正文,標題和部分。 讓我們假設我們有一個稱為“新聞”的板塊,並且有100萬條文章屬於新聞板塊。 因此,在這種情況下,如何優化以下查詢:
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萬條記錄,而其中一百萬條屬於一個節,則數據庫將掃描一百萬行。
在article.auther_id上添加索引。 除了您已經在日期和部分中添加的索引。
從查詢來看,您似乎需要在節上創建索引並在日期上創建索引(兩個單獨的索引)。 嘗試添加這些內容,然后查看說明計划,以查看它們是否有效,或者是否存在其他一些可能有所幫助的調整。
好的,首先將DATE
數據類型用於日期,因為這將比使用VARCHAR
快得多。
其次,您只需要在商品表的創建表語法中添加以下鍵即可。
KEY auther_id (auther_id),
KEY section (section),
沒什么關系,但是如果您使用的是InnoDB,則可以另外將auther_id用作外鍵。
另外,如果您不需要使用' LIKE
',請-只需檢查section="news"
就會更快。 (如果有一個有限的列表,您甚至可以對部分使用ENUM
。)
就像其他人所說的那樣,日期,部分和auther_id上的索引。 根據這個:
http://www.mysqlperformanceblog.com/2008/08/22/multiple-column-index-vs-multiple-indexes/
擁有一個多列索引而不是三個獨立的索引可能會非常有益,例如:
...
key idx_combo (auther_id, section, date)
...
在表定義中。
最好的辦法是根據日期/節創建一個分區表。
然后創建本地分區索引,以使性能更高。
您需要在(section, date)
上創建索引。
不要將auther_id
列為auther_id
列:文章將成為連接的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, ''
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.