Chinaunix

标题: [数据库优化]请教:有没有办法可以避免使用COUNT以改善性能? [打印本页]

作者: soichiro    时间: 2005-12-11 19:47
标题: [数据库优化]请教:有没有办法可以避免使用COUNT以改善性能?
我用一个表来储存用户数据,用户每次从客户端查询的时候都必须告诉用户他个人共有多少条记录,现在我是用COUNT来做的:

  1. SELECT COUNT(id) FROM table WHERE uid = 'user_id'
复制代码


问题是在表中记录增长以后性能恶化非常严重,现在记录已经接近100万条,查看MySQL状态发现随时都有无数个Locked,都是上面这条查询,现在数据库服务器CPU占用随时都在90%以上(双路Xeon 3G, Linux kernel 2.6.14, MySQL 5)。
原来我用的方法是专门用一个表来储存用户个人的总记录数,这样就不会有性能问题,但会由于客户端的异常中止而造成统计数字与实际记录不符(例如记录写入后程序异常中止,没有写入记录数统计+1)。

请问有没有什么好的办法能够解决这个问题?谢谢!

[ 本帖最后由 yejr 于 2005-12-12 13:42 编辑 ]
作者: rardge    时间: 2005-12-12 10:23
原帖由 soichiro 于 2005-12-11 19:47 发表
但会由于客户端的异常中止而造成统计数字与实际记录不符(例如记录写入后程序异常中止,没有写入记录数统计+1)。


用支持事务的数据表类型来做,比如InnoDB。
作者: 北京野狼    时间: 2005-12-12 10:34
原帖由 soichiro 于 2005-12-11 19:47 发表
我用一个表来储存用户数据,用户每次从客户端查询的时候都必须告诉用户他个人共有多少条记录,现在我是用COUNT来做的:

  1. SELECT COUNT(id) FROM table WHERE uid = 'user_id'
复制代码


问题是在表中记录增 ...


应该在用户每次更新记录的时候,有个数据库有字段为此+1,
这个数值不应该是count出来的
作者: hardiwang    时间: 2005-12-12 13:32
数据库优化下,我这里和你差不多112W条数据,你这样的查询,我需要0.05S,就完成了。不知道你的情况如何?
作者: 北京野狼    时间: 2005-12-12 13:50
楼上的,别总是喜欢吹牛

具体查询时间,要看表中的记录实际信息的情况,

这比你那1000个并发连接可能吹的更狠!
作者: hardiwang    时间: 2005-12-12 14:58
to:北京野狼
事实如此.我只是做了个最简单的实验而已。当然,每个人的database 是不一样的,我只是拿自己库的做实验。
不想和你理论,stop!
作者: soichiro    时间: 2005-12-12 16:58
原帖由 rardge 于 2005-12-12 10:23 发表


用支持事务的数据表类型来做,比如InnoDB。



感谢你的建议,我会考虑试试InnoDB,但我刚才想了一下,我用单独的表来保存用户记录总数的时候好像犯了一个错误,就是在客户端程序里我是先执行一条INSERT,然后再执行一条UPDATE来修改记录总数,这样如果客户端INSERT以后就中止了,那么UPDATE就没有执行。
那么如果我在客户端程序里用一条语句同时完成INSERT和UPDATE是否就解决了这个问题呢?
作者: 北京野狼    时间: 2005-12-12 17:01
  1. 这样如果客户端INSERT以后就中止了,那么UPDATE就没有执行。
复制代码


???????????????????????????
作者: soichiro    时间: 2005-12-12 17:04
原帖由 hardiwang 于 2005-12-12 13:32 发表
数据库优化下,我这里和你差不多112W条数据,你这样的查询,我需要0.05S,就完成了。不知道你的情况如何?


我有90W条数据,负载不高的情况下0.00 sec就执行完了,但负载高的时候就很慢,用show processlist一看全是Locked.
作者: rainloftty    时间: 2005-12-12 17:11
弱弱的说一句,我的msyql查询select count(*) 100多万记录也挺快的.
作者: 北京野狼    时间: 2005-12-12 17:16
原帖由 rainloftty 于 2005-12-12 17:11 发表
弱弱的说一句,我的msyql查询select count(*) 100多万记录也挺快的.


有1000W count也未必慢,主要看where的条件是什么
作者: qingmedia    时间: 2005-12-12 18:58
我不久前也问了同样的问题,查了mysql手册也没有说可以优化。
我使用的结果是,select count(*)如不带where条件就快,带条件怎么也快不了,我的库1000K条记录,大概300MB,时间大概从几秒到几十秒间,索引也没用。

我现在还没找到好办法,只是跟上面类似,用一个表记录更新count数用于分页,为防止偶尔的出入,设定手动后台完全更新。
作者: rardge    时间: 2005-12-13 10:59
原帖由 soichiro 于 2005-12-12 16:58 发表
就是在客户端程序里我是先执行一条INSERT,然后再执行一条UPDATE来修改记录总数,这样如果客户端INSERT以后就中止了,那么UPDATE就没有执行。
那么如果我在客户端程序里用一条语句同时完成INSERT和UPDATE是否就解决了这个问题呢?


那是你还不了解什么是事务,你去了解一下就知道,它就是解决这个问题的。把若干sql查询语句逻辑上合并为一原子操作,就好像只下达一条sql语句一样,结果就是:要么全部成功,只要有一个地方出错就全部回卷,相当于没有发送过指令。
另外,用另外一个表来记录自增id,使用 mysql 的 last_insert_id() 或者 mysql_insert_id(),它们保证在处理客户端并发的时候不会取错数据。
作者: hardiwang    时间: 2005-12-14 12:12
用事务是能很好解决这个问题!
作者: wildlily980    时间: 2005-12-14 14:46
如果那个表有个主键的话,应该是很快的吧?除非你的where条件使用了没有索引的列。
作者: 随风漂    时间: 2005-12-15 13:03
标题: 如果是不带where条件进行查询的话,建议创建一个记数表。
如果带where条件的话,可考虑是否创建了合适的索引了。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2