2010-09-15 65 views
1

這裏是日誌輸出:幫助消除MySQL的文件排序

# Time: 100915 13:06:49 
# [email protected]: ss[ss] @ localhost [] 
# Query_time: 13.978355 Lock_time: 0.000029 Rows_sent: 10 Rows_examined: 562760 
use ss; 
SET timestamp=1284574009; 

    SELECT DISTINCT 
     SQL_CALC_FOUND_ROWS 
     B.*, 
     U.username 
    FROM sc_users AS U, 
     sc_bookmarks AS B  
    WHERE B.uId = U.uId 
    AND B.bStatus = 0 
GROUP BY B.bHash 
ORDER BY B.bModified DESC 
    LIMIT 10; 

和解釋輸出:

id select_type table type possible_keys key key_len ref rows Extra 
---------------------------------------------------------------------------------------------------- 
1 SIMPLE U ALL PRIMARY NULL NULL NULL 2 Using temporary; Using filesort 
1 SIMPLE B ALL sc_bookmarks_usd NULL NULL NULL 187586 Using where; Using join buffer 

更新:這是由於sc_users創建語句OMGPonies/BrianHooper :-)

CREATE TABLE `sc_users` (
    `uId` int(11) NOT NULL AUTO_INCREMENT, 
    `username` varchar(25) NOT NULL DEFAULT '', 
    `password` varchar(40) NOT NULL DEFAULT '', 
    `uDatetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `uModified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `name` varchar(50) DEFAULT NULL, 
    `email` varchar(50) NOT NULL DEFAULT '', 
    `homepage` varchar(255) DEFAULT NULL, 
    `uContent` text, 
    PRIMARY KEY (`uId`) 
)  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; 

更多詳細資料(感謝馬克·拜爾斯):

該查詢由開源項目semanticscuttle生成以生成主頁。我不知道爲什麼查詢是按原樣寫的,因爲我只是在這個項目中弄溼了我的腳。 You can see the source where this sql is generated here though.

我已經嘗試添加各種索引和組合索引,沒有運氣加快查詢或刪除文件掃描。任何提示都表示讚賞!

更新:減慢是由ORDER BY語句造成的...... 查詢波紋管在4秒內以ORDER BY運行,0.01秒內沒有它。 任何想法爲什麼/如何解決它?

SELECT DISTINCT SQL_CALC_FOUND_ROWS B.*, U.username 
FROM sc_users AS U, sc_bookmarks AS B 
WHERE B.uId = U.uId 
AND B.bStatus = 0 
GROUP BY B.bHash 
ORDER BY B.bModified DESC 

更新:全新SQL和索引Quassnoi在回答中波紋管......這對我來說看起來很大,但實際上增加了執行時間,並沒有擺脫文件各種各樣的:

EXPLAIN SELECT SQL_CACHE b.*, u.username FROM (  SELECT DISTINCT bHash   FROM sc_bookmarks b   WHERE bStatus = 0  ) bd JOIN sc_bookmarks b ON  b.bId =   (  SELECT bId   FROM sc_bookmarks bi   WHERE bi.bStatus = 0     AND bi.bHash = bd.bHash   ORDER BY     bStatus DESC, bHash DESC, bModified DESC, bId DESC   LIMIT 1  ) JOIN sc_users u ON  u.uId = b.uId ORDER BY   bModified ASC LIMIT 10; 
+----+--------------------+------------+--------+--------------------------+------------------+---------+----------+--------+---------------------------------+ 
| id | select_type  | table  | type | possible_keys   | key    | key_len | ref  | rows | Extra       | 
+----+--------------------+------------+--------+--------------------------+------------------+---------+----------+--------+---------------------------------+ 
| 1 | PRIMARY   | <derived2> | ALL | NULL      | NULL    | NULL | NULL  | 187565 | Using temporary; Using filesort | 
| 1 | PRIMARY   | b   | eq_ref | PRIMARY,sc_bookmarks_usd | PRIMARY   | 4  | func  |  1 | Using where      | 
| 1 | PRIMARY   | u   | eq_ref | PRIMARY,su_idx   | PRIMARY   | 4  | ss.b.uId |  1 |         | 
| 3 | DEPENDENT SUBQUERY | bi   | ref | sc_bookmarks_hui,bStatus | sc_bookmarks_hui | 98  | bd.bHash |  1 | Using where; Using filesort  | 
| 2 | DERIVED   | b   | ref | bStatus     | bStatus   | 1  |   | 94556 | Using where; Using index  | 
+----+--------------------+------------+--------+--------------------------+------------------+---------+----------+--------+---------------------------------+ 

更新:根據Quassnoi的請求,這裏是sc_bookmarks的CREATE TABLE語句。

CREATE TABLE `sc_bookmarks` (
`bId` int(11) NOT NULL AUTO_INCREMENT, 
`uId` int(11) NOT NULL DEFAULT '0', 
`bIp` varchar(40) DEFAULT NULL, 
`bStatus` tinyint(1) NOT NULL DEFAULT '0', 
`bDatetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
`bModified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
`bTitle` varchar(255) NOT NULL DEFAULT '', 
`bAddress` varchar(1500) NOT NULL, 
`bDescription` text, 
`bPrivateNote` text, 
`bHash` varchar(32) NOT NULL DEFAULT '', 
`bVotes` int(11) NOT NULL, 
`bVoting` int(11) NOT NULL, 
`bShort` varchar(16) DEFAULT NULL, 
PRIMARY KEY (`bId`), 
KEY `sc_bookmarks_usd` (`uId`,`bStatus`,`bDatetime`), 
KEY `sc_bookmarks_hui` (`bHash`,`uId`,`bId`), 
KEY `sc_bookmarks_du` (`bDatetime`,`uId`), 
KEY `sc_bookmarks_modified_idx` (`bModified`), 
KEY `bStatus` (`bStatus`,`bHash`,`bModified`,`uId`,`bId`), 
KEY `bHash` (`bHash`), 
CONSTRAINT `sc_bookmarks_ibfk_1` FOREIGN KEY (`uId`) REFERENCES `sc_users` (`uId`), 
CONSTRAINT `sc_bookmarks_ibfk_2` FOREIGN KEY (`uId`) REFERENCES `sc_users` (`uId`) 
) ENGINE=InnoDB AUTO_INCREMENT=187566 DEFAULT CHARSET=utf8 

更新jacobs反饋cwiske的答案。 該查詢已經過優化,但不會返回與原始查詢相同的結果。

例如,我在表「sc_bookmarks」中有3個條目。

bId   bModified  bHash 
------------------------------------ 
2000-11-10 aaaaaa   ... 
2011-12-12 bbbbbb   ... 
2010-11-11 aaaaaa   ... 

該查詢應該只返回行ID爲1和2.但它會返回所有3條記錄。好像MySQL不喜歡:'GROUP BY B.bModified DESC,B.bHash DESC'

我試圖改變'GROUP BY B.bModified DESC,B.bHash DESC'

到'GROUP基於B .bModified,B.bHash GROUP BY B.bHash,B.bModified'

但我仍然得到所有3條記錄。

它在我離開'通過B.bHash組羣'時工作,但阻止索引工作。

+0

filesort在'sc_users'表上 - 請爲它發佈CREATE TABLE語句。 – 2010-09-15 22:16:16

+0

當您擁有GROUP BY時,DISTINCT的用途是什麼? GROUP BY是否已經保證結果集中B.bHash的值是不同的?你是否意識到,在結果中包含不在組中的列可能會導致在某些情況下不確定的結果?也許你可以解釋你想做什麼? – 2010-09-15 22:23:05

+0

呃...它看起來像你張貼錯誤的表的代碼... – 2010-09-16 13:36:07

回答

2

我試試你的查詢cweiske。

這個偉大的工程,沒有「使用臨時」或「使用文件排序」

但它返回錯誤的記錄。

例如,我在表「sc_bookmarks」中有3個條目。

出價,bModified,bHash,...

1,2000年11月10日,AAAAAA,......

2,2011-12-12,BBBBBB,...

3,2010-11-11,aaaaaa,...

所以我期望您的查詢只返回行ID爲1和2.但它會返回所有3條記錄。看起來像MySQL不喜歡 「GROUP BY B.bModified DESC,B.bHash DESC」

我試圖改變 「GROUP BY B.bModified DESC,B.bHash DESC」 到

  • GROUP BY B.bModified,B.bHash

  • GROUP BY B.bHash,B.bModified

,但新工作正常,仍然得到3條記錄。

只有當我離開「GROUP BY B.bHash」時才起作用,但在這種情況下索引不起作用。

1

它可能不會傷害到運行ANALYZE TABLE first

ANALYZE TABLE sc_users; 
ANALYZE TABLE sc_bookmarks; 

讓我們來看看有沒有改善,如果你add the following index

CREATE INDEX su_idx USING BTREE ON SC_USERS(uid, username) 
+0

感謝您的建議。我添加了索引,並運行了分析表,但不幸的是,它並沒有改變運行時間或解釋語句的結果。 – Eric 2010-09-17 00:09:34

1

我相信你想檢索每個哈希值與用戶上次修改書籤與之相關聯。

假設上sc_bookmarksPRIMARY KEY列名爲id

SELECT b.*, u.username 
FROM (
     SELECT DISTINCT bHash 
     FROM sc_bookmarks b 
     WHERE bStatus = 0 
     ) bd 
JOIN sc_bookmarks b 
ON  b.id = 
     (
     SELECT id 
     FROM sc_bookmarks bi 
     WHERE bi.bStatus = 0 
       AND bi.bHash = bd.bHash 
     ORDER BY 
       bStatus DESC, bHash DESC, bModified DESC, id DESC 
     LIMIT 1 
     ) 
JOIN sc_users u 
ON  u.uId = b.uId 
ORDER BY 
     bModified DESC 
LIMIT 10 

sc_bookmarks (bStatus, bHash bModified, id)爲此創建索引快速地工作。

+0

感謝您的想法。我發佈了上面新解釋的結果。不幸的是,它仍然在執行2個文件類別,並且需要更長時間(我也創建了建議的索引) – Eric 2010-09-17 00:10:49

1

爲了獲得最佳性能,查詢需要如下:

SELECT U.username, B.* 
FROM sc_users AS U, sc_bookmarks AS B 
WHERE B.uId = U.uId AND B.bStatus = 0 
GROUP BY B.bModified DESC, B.bHash DESC 
ORDER BY B.bModified DESC 
LIMIT 10 

,你應該創建狀態+修飾+哈希組合索引。

+0

謝謝,我今天要試一試。 – Eric 2010-09-20 02:43:36

+0

我也將在SemanticScuttle中實現它,但這看起來有點難度,需要一些時間。 – cweiske 2010-09-20 08:43:24

+0

cweiske,請參閱jakub的更新,我也將其添加到我的原始問題中。謝謝,--Eric – Eric 2010-09-24 13:43:30