2010-09-15 67 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