2013-05-08 148 views
3

我需要抽出一點我的查詢,因爲它在大型數據庫上花費太長時間。MySql:需要改進查詢的性能

我有以下表

vb_user 

+++++++++++++++++++++++++++++++++

++用戶ID ++的用戶名+職位++

++++++++++++++++++++++++++++++++ +

vb_post 

++++++++++++++++++++++++

++用戶ID ++界線++

++++++++++++++++++++++++

我用這個查詢

SELECT VBU.userid AS USER_ID 
, VBU.username AS USER_NAME 
, COUNT(VBP.userid) AS NUMBER_OF_POSTS_FOR_30_DAYS 
      , FROM_UNIXTIME(VBU.joindate) as JOIN_DATE 
     FROM vb_user AS VBU 
     LEFT JOIN vb_post AS VBP 
     ON VBP.userid = VBU.userid 
      WHERE VBU.joindate BETWEEN '__START_DATE__' AND '__END_DATE__' 
       AND VBP.dateline BETWEEN VBU.joindate AND DATE_ADD(FROM_UNIXTIME(VBU.joindate), INTERVAL 30 DAY) 
      GROUP BY VBP.userid 
      ORDER BY NUMBER_OF_POSTS_FOR_30_DAYS DESC" 

我不得不選擇誰已經公佈,從他們加入,直到30天后大多數用戶.....我無法弄清楚如何做到這一點的withouth的功能FROM_UNIXTIME ..

但它需要很多時間。有關如何提高查詢性能的任何想法?

這裏是輸出解釋

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra 
1,SIMPLE,VBP,index,userid,threadid_visible_dateline,18,NULL,2968000,"Using where; Using index; Using temporary; Using filesort" 
1,SIMPLE,VBU,eq_ref,PRIMARY,PRIMARY,4,vb_copilul.VBP.userid,1,"Using where" 

這裏是關於表的信息

Table,"Create Table" 
vb_user,"CREATE TABLE `vb_user` (
    `userid` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `username` varchar(100) NOT NULL DEFAULT '', 
    `posts` int(10) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`userid`), 
    KEY `usergroupid` (`usergroupid`), 
) ENGINE=MyISAM AUTO_INCREMENT=101076 DEFAULT CHARSET=latin1" 

Table,"Create Table" 
vb_post,"CREATE TABLE `vb_post` (
`postid` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`threadid` int(10) unsigned NOT NULL DEFAULT '0', 
`parentid` int(10) unsigned NOT NULL DEFAULT '0', 
`username` varchar(100) NOT NULL DEFAULT '', 
`userid` int(10) unsigned NOT NULL DEFAULT '0', 
`title` varchar(250) NOT NULL DEFAULT '', 
`dateline` int(10) unsigned NOT NULL DEFAULT '0', 
`pagetext` mediumtext, 
`allowsmilie` smallint(6) NOT NULL DEFAULT '0', 
`showsignature` smallint(6) NOT NULL DEFAULT '0', 
`ipaddress` char(15) NOT NULL DEFAULT '', 
`iconid` smallint(5) unsigned NOT NULL DEFAULT '0', 
`visible` smallint(6) NOT NULL DEFAULT '0', 
`attach` smallint(5) unsigned NOT NULL DEFAULT '0', 
`infraction` smallint(5) unsigned NOT NULL DEFAULT '0', 
`reportthreadid` int(10) unsigned NOT NULL DEFAULT '0', 
PRIMARY KEY (`postid`), 
KEY `userid` (`userid`), 
KEY `threadid` (`threadid`,`userid`), 
KEY `threadid_visible_dateline` (`threadid`,`visible`,`dateline`,`userid`,`postid`), 
KEY `dateline` (`dateline`), 
KEY `ipaddress` (`ipaddress`) 
) ENGINE=MyISAM AUTO_INCREMENT=3009320 DEFAULT CHARSET=latin1" 
+1

你有沒有做對的查詢的解釋?如果是這樣,那告訴你什麼? – 2013-05-08 10:31:38

+0

yay在EXPLAIN上。你能否發佈完整的表格定義?最好使用'SHOW CREATE TABLE vb_user'和'SHOW CREATE TABLE vb_post'的結果,甚至可以使用'INSERT INTO ....'語句形式的一些示例數據。 – VolkerK 2013-05-08 10:43:17

回答

3

有兩件事情可以做,以提高查詢:

  • 不要將VBP.datetime轉換爲unix時間。直接使用帶日期的BETWEEN查詢。在您的查詢中,服務器必須轉換數據庫中的所有日期以進行比較,而不是使用本機類型。如果您總是使用datetime列作爲unix時間戳,那麼將其聲明爲Double(我認爲?)而不是DATETIME(或TIMESTAMP - 無論您選擇了什麼)。這樣你也可以加速其他操作。
  • 將索引添加到datetime列以確保查詢之間足夠快。

其他的一切看起來不錯

+0

我剛剛看到了解釋並創建了添加的表語句 - 是的,日期行列已經是int類型。查看說明查詢 - 它確實使用了一個非常複雜的鍵,但仍能掃描數千行。因此,請嘗試刪除轉換,然後嘗試刪除該threadid_visible_dateline鍵 - 它可以強制它使用更好的鍵。 – 2013-05-08 11:22:48

+0

真的,它需要在日期和用戶ID上的索引。 – symcbean 2013-05-08 11:28:01

+0

當然,那麼應該有一個,但在太多的領域添加索引可能是有害的!所以我的建議是首先放下那個索引,看看它是怎麼回事。之後(你是對的)嘗試在這兩個字段上添加一個索引。我不確定MySQL在選擇索引時有多聰明 - 必須試着看看它是否會更喜歡那個索引。 – 2013-05-08 11:40:48