2017-09-05 64 views
5

我正在開發一個社交網絡跟蹤應用程序。即使連接適當的索引工作正常。但是,當我添加order by子句時,總查詢需要100倍的時間來執行。以下查詢我用於獲取twitter_users而不使用order by子句。如何通過在mysql中加入表現來改善訂單

SELECT DISTINCT `tracked_twitter`.id 
FROM tracked_twitter 
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id` 
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id` 
AND `tracker_twitter_content`.`tracker_id` = '88' 
LIMIT 20 

顯示行0 - 19(20總計,查詢花費0.0714秒)

但是,當我通過子句添加順序(在索引列)

SELECT DISTINCT `tracked_twitter`.id 
FROM tracked_twitter 
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id` 
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id` 
AND `tracker_twitter_content`.`tracker_id` = '88' 
ORDER BY tracked_twitter.followers_count DESC 
LIMIT 20 

顯示行0 - 19( 20總計,查詢花費13.4636秒)

EXPLAIN enter image description here

當我在它的單獨表子句執行的命令其不花費太多時間

SELECT * FROM `tracked_twitter` WHERE 1 order by `followers_count` desc limit 20 

顯示行0 - 19(20總計,查詢花費0.0711秒)[FOLLOWERS_COUNT:68236387 - 10525612]

該表的創建語句如下

CREATE TABLE IF NOT EXISTS `tracked_twitter` (
    `id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `handle` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `description` text COLLATE utf8_unicode_ci, 
    `profile_image` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `followers_count` int(11) NOT NULL, 
    `is_influencer` tinyint(1) NOT NULL DEFAULT '0', 
    `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `gender` enum('Male','Female','Other') COLLATE utf8_unicode_ci 
    DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `followers_count` (`followers_count`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

因此,加入由工作良好,當我執行它在其表沒有減速的查詢和訂單。那麼我該如何提高性能?

UPDATE 1

@GordonLinoff方法解決,如果我只需要結果從父表中設置。我想知道每個人的推文數(與tracked_twitter表匹配的twitter_content的計數)。我如何修改它?如果我想在推特內容上使用數學函數,我該怎麼做?

SELECT `tracked_twitter` . * , COUNT(*) AS twitterContentCount, retweet_count + favourite_count + reply_count AS engagement 
FROM `tracked_twitter` 
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id` 
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id` 
WHERE `is_influencer` != '1' 
AND `tracker_twitter_content`.`tracker_id` = '88' 
AND `tracked_twitter_id` != '0' 
GROUP BY `tracked_twitter`.`id` 
ORDER BY twitterContentCount DESC 
LIMIT 20 
OFFSET 0 
+0

如果刪除了「LIMIT」子句,無序查詢需要多長時間?無序結果集中的「LIMIT」基本意思是「給我20條符合我的標準的記錄」,而在有序的結果中,它意味着「找到符合我的標準的前20條記錄」,這基本上意味着你必須標識所有其中。 –

+0

查詢中的'EXPLAIN'的輸出是什麼? – raina77ow

+0

@ raina77ow我加了解釋圖片 – Tamizharasan

回答

3

試着擺脫distinct。這是一個性能殺手。我不確定爲什麼您的第一個查詢很快就會生效;也許MySQL很聰明,可以優化它。

我會嘗試:

SELECT tt.id 
FROM tracked_twitter tt 
WHERE EXISTS (SELECT 1 
       FROM twitter_content tc INNER JOIN 
        tracker_twitter_content ttc 
        ON tc.id = ttc.twitter_content_id 
       WHERE ttc.tracker_id = 88 AND 
        tt.id = tc.tracked_twitter_id 
      ) 
ORDER BY tt.followers_count DESC ; 

對於此版本,您想對指數:tracked_twitter(followers_count, id)twitter_content(tracked_twitter_id, id)tracker_twitter_content(twitter_content_id, tracker_id)

+0

它的工作完美,並通過子句順序沒有減慢查詢執行(總計20,查詢花了0.0707秒)。如果你解釋查詢,我會很高興。這樣我就可以獲得這種方法的知識。如果您有任何參考鏈接可以閱讀有關這些方法的信息,它將很有用。感謝您的回答。 – Tamizharasan

+0

我想第一個查詢很快就會起作用,因爲MySQL知道它只需要從一個無序集合中收集20個不同的記錄,這可能來自於少量的行(比方說20個以上但少於1000個)。從有序的數以百萬計的條目中獲得前20個特徵將會慢得多 - 不同的要麼是一個紅色的鯡魚,要麼是花費時間,或者MySQL可能已經足夠愚蠢,不僅需要訂購,而且那麼在返回僅有20 –

+0

@CaiusJard之前還要有數百萬行。 。 。實際上,我認爲MySQL可以使用'id'上的索引來防止重複 - 它只是按順序讀取索引。使用明確的'ORDER BY',這是不可能的。 –

1

父表保持在支架與限制

SELECT DISTINCT `tracked_twitter`.id FROM 
(SELECT id,followers_count FROM tracked_twitter ORDER BY followers_count DESC 
LIMIT 20) AS tracked_twitter 
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id` 
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id` 
AND `tracker_twitter_content`.`tracker_id` = '88' 
ORDER BY tracked_twitter.followers_count DESC 
+0

它不能是答案。因爲你沒有考慮其他表的約束條件。所以它只需要父表中的20條記錄並與其他人聯合。當我執行查詢時,我只有兩行。 – Tamizharasan

1

的主要問題是,即使你有相對較少的行,你用varchar(255) COLLATE utf8_unicode_ci作爲主鍵(而不是整數),因此作爲外鍵其他表格。我懷疑同樣的問題是twitter_content.id。這會導致很多長字符串比較,併爲臨時表保留大量額外的內存。

關於查詢本身,是的,它應該是一個查詢,沿着followers_count索引走,並檢查相關表的條件。這可以按Gordon Linoff的建議完成,或者使用索引提示。