2009-07-09 24 views
1

這裏的查詢:任何關心幫助優化MySQL查詢?

SELECT COUNT(*) AS c, MAX(`followers_count`) AS max_fc, 
     MIN(`followers_count`) AS min_fc, MAX(`following_count`) AS max_fgc, 
     MIN(`following_count`) AS min_fgc, SUM(`followers_count`) AS fc, 
     SUM(`following_count`) AS fgc, MAX(`updates_count`) AS max_uc, 
     MIN(`updates_count`) AS min_uc, SUM(`updates_count`) AS uc 
FROM `profiles` 
WHERE `twitter_id` IN (SELECT `followed_by` 
         FROM `relations` 
         WHERE `twitter_id` = 123); 

這兩個表是profilesrelations。兩者都有超過1,000,000行InnoDB引擎。兩者都有索引twitter_id,relations有一個額外的索引(twitter_idfollowed_by)。查詢需要6秒鐘才能執行,這讓我非常失望。我知道我可以以某種方式加入,但我的MySQL知識並不那麼酷,這就是爲什麼我要求你的幫助。

在此先感謝大家=)

乾杯, K〜

更新

好吧,我設法降低到2.5秒。我使用INNER JOIN並添加了三個索引對。這裏的解釋結果:

id, select_type, table, type, possible_keys, 
    key, key_len, ref, rows, Extra 

1, 'SIMPLE', 'r', 'ref', 'relation', 
    'relation', '4', 'const', 252310, 'Using index' 

1, 'SIMPLE', 'p', 'ref', 'PRIMARY,twiter_id,id_fc,id_fgc,id_uc', 
    'id_uc', '4', 'follerme.r.followed_by', 1, '' 

希望這有助於。

另一個更新

這裏是SHOW CREATE TABLE語句兩個表:

CREATE TABLE `profiles` (
    `twitter_id` int(10) unsigned NOT NULL, 
    `screen_name` varchar(45) NOT NULL default '', 
    `followers_count` int(10) unsigned default NULL, 
    `following_count` int(10) unsigned default NULL, 
    `updates_count` int(10) unsigned default NULL, 
    `location` varchar(45) default NULL, 
    `bio` varchar(160) default NULL, 
    `url` varchar(255) default NULL, 
    `image` varchar(255) default NULL, 
    `registered` int(10) unsigned default NULL, 
    `timestamp` int(10) unsigned default NULL, 
    `relations_timestamp` int(10) unsigned default NULL, 
    PRIMARY KEY USING BTREE (`twitter_id`,`screen_name`), 
    KEY `twiter_id` (`twitter_id`), 
    KEY `screen_name` USING BTREE (`screen_name`,`twitter_id`), 
    KEY `id_fc` (`twitter_id`,`followers_count`), 
    KEY `id_fgc` (`twitter_id`,`following_count`), 
    KEY `id_uc` (`twitter_id`,`updates_count`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

CREATE TABLE `relations` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `twitter_id` int(10) unsigned NOT NULL default '0', 
    `followed_by` int(10) unsigned default NULL, 
    `timestamp` int(10) unsigned default NULL, 
    PRIMARY KEY USING BTREE (`id`,`twitter_id`), 
    UNIQUE KEY `relation` (`twitter_id`,`followed_by`) 
) ENGINE=InnoDB AUTO_INCREMENT=1209557 DEFAULT CHARSET=utf8 

哇,什麼亂七八糟=)對不起!

回答

1

創建以下綜合指數:

profiles (twitter_id, followers_count) 
profiles (twitter_id, following_count) 
profiles (twitter_id, updates_count) 

和後期查詢計劃,偏偏。

順便說一下,這COUNT(*)返回多少行?

更新:

你的錶行是很長。您選擇的所有字段創建一個綜合指數:

profiles (twitter_id, followers_count, following_count, updates_count) 

,以便JOIN查詢可以檢索它從該指數所需要的所有值。

+0

謝謝!創建索引對,id_fc,id_fgc,id_uc。似乎已經省了我〜300毫秒。查詢計劃?你的意思是說明結果?看看qestion更新。 – kovshenin 2009-07-09 15:11:47

3

聯接會是這個樣子:

SELECT COUNT(*) AS c, 
MAX(p.`followers_count`) AS max_fc, 
MIN(p.`followers_count`) AS min_fc, 
MAX(p.`following_count`) AS max_fgc, 
MIN(p.`following_count`) AS min_fgc, 
SUM(p.`followers_count`) AS fc, 
SUM(p.`following_count`) AS fgc, 
MAX(p.`updates_count`) AS max_uc, 
MIN(p.`updates_count`) AS min_uc, 
SUM(p.`updates_count`) AS uc 
FROM `profiles` AS p 
INNER JOIN `relations` AS r ON p.`twitter_id` = r.`followed_by` 
WHERE r.`twitter_id` = 123; 

爲了幫助優化它,你應該運行EXPLAIN SELECT ...在這兩個查詢。

+0

連接會減慢這種速度。 – corymathews 2009-07-09 15:03:36

+0

這將執行時間從6秒減少到3秒 – kovshenin 2009-07-09 15:10:10

1
SELECT COUNT(*) AS c, 
    MAX(`followers_count`) AS max_fc, MIN(`followers_count`) AS min_fc, 
    MAX(`following_count`) AS max_fgc, MIN(`following_count`) AS min_fgc, 
    SUM(`followers_count`) AS fc, SUM(`following_count`) AS fgc, 
    MAX(`updates_count`) AS max_uc, MIN(`updates_count`) AS min_uc, SUM(`updates_count`) AS uc 
FROM `profiles` 
JOIN `relations` 
    ON (profiles.twitter_id = relations.followed_by) 
WHERE relations.twitted_id = 123; 

可能會快一點,但您需要測量並檢查是否確實如此。

+0

我採用了上述方法,但我認爲這兩者沒有什麼區別。 – kovshenin 2009-07-09 15:10:48

+0

是的,在如何/如果你打破線條或表別名和字段資格的差異並不重要(除非你需要使用別名和/或資格,如果需要消除歧義,但我沒有看到任何痕跡這裏)。 – 2009-07-09 15:39:00

1

count(*)是InnoDB引擎下的一個非常昂貴的操作,你是否試過這個查詢而沒有這個部分?如果它造成的處理時間最長,那麼也許你可以保留一個運行值,而不是每次查詢它。

1

我會從程序員的角度來解決這個問題;我有一個單獨的表(或某處的存儲區域),用於存儲與原始查詢中每個字段關聯的最大值,最小值和總值,並在每次更新並添加表記錄時更新這些值。 (儘管刪除可能會有問題,如果不正確處理)。

完成原始查詢以填充這些值後(與發佈的查詢幾乎相同)後,您基本上將最終查詢從數據表中減少爲一行,而不是計算所有內容立刻。