2011-11-20 119 views
2

我在我的MySQL數據庫,用戶和微博兩個表,如下:如何加快MySQL數據庫/查詢?

TABLE users (
    uid int(7) NOT NULL AUTO_INCREMENT, 
    twitter_uid int(10) NOT NULL, 
    screen_name varchar(255) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    tweets int(6) NOT NULL, 
    followers_count int(7) NOT NULL, 
    statuses_count int(7) NOT NULL, 
    created_at int(10) NOT NULL, 
    PRIMARY KEY (uid) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

TABLE tweets (
    tweet_id int(11) NOT NULL AUTO_INCREMENT, 
    `query` varchar(5) NOT NULL, 
    id_str varchar(18) NOT NULL, 
    created_at int(10) NOT NULL, 
    from_user_id int(11) NOT NULL, 
    from_user varchar(256) NOT NULL, 
    `text` text NOT NULL, 
    PRIMARY KEY (tweet_id), 
    KEY id_str (id_str) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

的鳴叫表包含了超過200萬的記錄。我已將唯一用戶(來自tweets.from_user)放入用戶表中。它現在包含94,100個用戶。我現在要算微博每個用戶提出的數量,如下(PHP):

res = db_query('SELECT uid, screen_name FROM users WHERE tweets = 0 LIMIT 150'); 
while ($user = db_fetch_object($result)) { 
    $res2 = db_query(
    "SELECT COUNT(tweet_id) FROM tweets WHERE from_user = '%s'", 
    $user->screen_name 
); 
    $cnt = db_result($result2); 
    db_query("UPDATE users SET tweets = %d WHERE uid = %d", $cnt, $user->uid); 
} 

此代碼然而,極其緩慢。計算150個用戶的推文需要大約5分鐘的時間。按照這個速度,對於所有用戶來說完成這個任務大概需要3天的時間。

我的問題是 - 我必須在這裏丟失一些東西。也許有更高效的查詢可能,或者我應該改變一些數據庫結構?任何幫助將不勝感激:)

+1

查看Quassnoi的網站http://explainextended.com,看他的例子,也許問他 – david

回答

6

我認爲這裏最糟糕的問題是有多個查詢。這很可能比索引問題更糟糕。你應該嘗試只有一個查詢。

UPDATE users 
SET users.tweets = (SELECT COUNT(tweet_id) 
        FROM tweets 
        WHERE tweets.from_user = users.uid 
        AND users.tweets =0 
        ) 
+1

+1我完全同意你的看法。在最壞的情況下,有151個「SELECT」查詢和150個「UPDATE」。所有這些都可以用1 UPDATE替換。 – a1ex07

+0

很酷。 :-)我不確定的一件事是他的限制......是真正需要的選擇,@Reveller? – maraspin

+0

由於整個事情的緩慢,極限就在那裏。我下載了WGET for windows並創建了一個計劃任務,每5分鐘運行一次上述代碼(以150個用戶爲增量),以防止Apache超過300秒超時限制:) – Pr0no

2

你有索引所有相關的屬性? escpecially from_user應該有一個索引!

1

第一步是將索引添加到頻繁用作搜索條件的列中。

+0

不能完全同意。第一步很可能是避免這麼多的查詢。當然,索引也很重要。胸圍最有可能不是這裏最糟糕的問題。毫無疑問,標杆和解釋可以成爲你的朋友,當然。 :-) – maraspin

+0

給定90k條目沒有索引,這對我來說是一個很大的禁忌。優化查詢本身並不是那麼低的掛果:P – prusswan

+0

我明白了你的觀點。考慮到實際上很有意義的數字。但是,從經驗來看,索引永遠不能取代糟糕的設計選擇。 ;-) – maraspin

2

我想通過冷凝所有這一切到一個單一的UPDATE語句開始:

UPDATE users 
    SET tweets = 
     (SELECT COUNT(1) 
      FROM tweets 
      WHERE tweets.from_user = users.screen_name 
     ) 
WHERE users.tweets = 0 
LIMIT 150 
; 

,然後我會看指數。尤其要確保tweets.from_user有一個索引。 (請參閱http://dev.mysql.com/doc/refman/5.0/en/create-index.html以瞭解如何在表列上創建索引。)

2

儘管通過將這些SQL語句「凝結」爲一個(如其他答案所建議的),可以顯着加快users.tweets的更新速度,當用戶發佈新推文時做什麼?如何知道users.tweets需要重新更新?

  • 一種方法是使觸發只要行被刪除或插入tweets表,或當tweets.from_user被修改,更新users.tweets
  • 您也可以完全刪除users.tweets,並根據需要動態計算tweets。

在任何情況下,要加快SELECT COUNT(tweet_id) FROM tweets WHERE from_user = '%s'查詢,您需要在{from_user}上創建一個索引。由於tweet_id不爲NULL,因此COUNT(tweet_id)等同於COUNT(*) - 否則將需要{from_user,tweet_id}上的組合索引。

+0

好點。並在盒子外思考;-) – maraspin

+0

享受10K特權! :) –