帮助删除mysql文件排序

时间:2010-09-15 22:12:53

标签: sql optimization mysql

这是日志输出:

# Time: 100915 13:06:49
# User@Host: 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

UPDATE:这是sc_users的create语句,感谢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 ;

更多细节(感谢Mark Byers):

此查询由开源项目语义切片生成,以生成主页。我不知道为什么查询是按原样编写的,因为我只是在这个项目中弄湿了。 You can see the source where this sql is generated here though.

我尝试过添加各种索引和组合索引,没有运气加快查询速度或删除文件扫描。任何提示都表示赞赏!

更新:减速是由ORDER BY语句引起的...... 下面的查询使用ORDER BY在4秒内运行,没有它的情况下运行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

更新了关于cwiske答案的jacobs反馈。 查询已得到很好的优化,但它不会返回与原始查询相同的结果。

例如,我在表“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'

to'GROUP BY B.bModified,B.bHash GROUP BY B.bHash,B.bModified'

但我仍然获得了所有3条记录。

当我离开'GROUP BY B.bHash'但它阻止了索引工作时,它有效。

4 个答案:

答案 0 :(得分:2)

我尝试你的查询cweiske。

这很好用,没有“使用临时”或“使用filesort”

但是它返回了错误的记录。

例如,我在表“sc_bookmarks”中有3个条目。

bId,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 :(得分: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) 

答案 2 :(得分:1)

我相信你想为每个哈希以及与之关联的用户检索最后修改过的书签。

假设PRIMARY KEY上的sc_bookmarks列被称为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)上创建一个索引,以便快速工作。

答案 3 :(得分: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

你应该在status + modified + hash上创建一个组合索引。