Submitted by gouki on 2013, March 21, 11:40 AM
在mysql里面,我们偶尔会有这样的sql出现:
select userid,count(userid) as cnt from xxxxxtable group by userid;
这样的sql在mongo里怎么实现呢?其实也相对比较简单
PHP代码
- <?php
- $mongo = new Mongo();
- $mongo->selectDB('xxx');
- $collection = $mongo->selectCollection('表');
-
- $field = array('userid'=>1);
- $cnt = array('cnt'=>0);
- $result = $collection->group($field,$cnt,"function(obj,pref){pref.cnt++;}");
打印出来的结果也很方便识别:
XML/HTML代码
- Array
- (
- [retval] => Array
- (
- [0] => Array
- (
- [userid] => 11111
- [cnt] => 2
- )
- //省略
- )
-
- [count] => 21
- [keys] => 11
- [ok] => 1
- )
果然轻轻松松啊
Tags: mongo, mysql
DataBase | 评论:0
| 阅读:20172
Submitted by gouki on 2012, December 28, 9:44 AM
这是昨天SAE分享的一篇文章,开始的时候,我看了一遍,发现好象没有什么特别的内容,但再仔细看的时候,发现居然可以这样做。。。
问题描述:
我们要访问的表是一个非常大的表,四千万条记录,id是主键,program_id上建了索引。
执行一条SQL:
select * from program_access_log where program_id between 1 and 4000
这条SQL非常慢。我们原以为处理记录太多的原因,所以加了id限制,一次只读五十万条记录
select * from program_access_log where id between 1 and 500000 and program_id between 1 and 4000
但是这条SQL仍然很慢,速度比上面一条几乎没有提升。Mysql处理50万条记录的表,条件字段还建了索引,这条语句应该是瞬间完成的。
问题分析:
这张表大约容量30G,数据库服务器内存16G,无法一次载入。就是这个造成了问题。
这条SQL有两个条件,ID一到五十万和Program_id一到四千,因为program_id范围小得多,mysql选择它做为主要索引。
先通过索引文件找出了所有program_id在1到4000范围里所有的id,这个过程非常快。
接下来要通过这些id找出表里的记录,由于这些id是离散的,所以mysql对这个表的访问不是顺序读取。
而这个表又非常大,无法一次装入内存,所以每访问一条记录mysql都要重新在磁盘上定位并把附近的记录都载入内存,大量的IO操作导致了速度的下降。
问题解决方案:
1. 以program_id为条件对表进行分区
2. 分表处理,每张表的大小不超过内存的大小
然而,服务器用的是mysql5.0,不支持分区,而且这个表是公共表,无法在不影响其它项目的条件下修改表的结构。所以我们采取了第三种办法:
select * from program_access_log where id between 1 and 500000 and program_id between 1 and 15000000
现在program_id的范围远大于id的范围,id被当做主要索引进行查找,由于id是主键,所以查找的是连续50万条记录,速度和访问一个50万条记录的表基本一样
总结:
这是一个在千万笔记录表中由于使用了索引导致了数据查找变慢的问题,有一定的典型性和大家交流下!
-----------
看我标红的那一段,原来还能够这样做,以前真的没有注意过,也从来没有想过,先利用主键做一次过滤。这样效率会好很多啊
上述内容来自:http://ourmysql.com/archives/108?f=wb,该网站还有很多技巧值得一看。
Tags: sae, mysql, 索引
DataBase | 评论:2
| 阅读:15440
Submitted by gouki on 2012, August 26, 11:09 AM
先申明一下,这个可能不是BUG。只是算起来是实现的方式不一样而已。
场景:我有一个MYSQL数据库,但是现在容量越来越大,主要是因为其中有大字段,多个大字段,所以在查询的时候会特别特别慢。所以想到用mongo来存储一些查询用的结构。单条的时候,我还是准备采用MYSQL。当然其实单条用mongo也合适。不过因为迁移数据有点麻烦,所以还是先忍忍,一步一步来。
测试阶段:因为MYSQL to MONGO有点小麻烦,没有现成的工具。官方说有mongoimport,我看过了,确实OK,但是只支持一些基础的结构,比如:json,csv等。其他的则需要第三方工具。但我自己先在测试中,所以就直接写了个脚本,先将数据用AR取出来。然后插入到mongo中。结果发现,在排序的时候。。9999比10000还大。问了一下神仙 ,他说这应该是按字符串排序的方式来做的。
于是做了一个测试,写进了一个数字,果然就对了。。难道是yii的AR的BUG?想想这不太应该啊。于是我写了一个小的Demo:
PHP代码
- $db = mysql_connect("localhost","root","123456");
- mysql_select_db("feed");
- $query = mysql_query("select id from feeds_group limit 1");
- while($rs = mysql_fetch_array($query)){
- $result = $rs;
- echo "<pre>";
- var_dump($result);
- echo "</pre>";
- }
- echo "<hr />";
- $dsn = 'mysql:host=localhost;dbname=feed';
- $user = 'root';
- $password = '123456';
- $dbh = new PDO($dsn, $user, $password);
- $sth = $dbh->prepare("select id from feeds_group limit 1");
- $sth->execute();
- $result = $sth->fetchAll();
- echo "<pre>";
- var_dump($result);
- echo "</pre>";
打印出来一看:
XML/HTML代码
- array(2) {
- [0]=>
- string(1) "1"
- ["id"]=>
- string(1) "1"
- }
-
- array(1) {
- [0]=>
- array(2) {
- ["id"]=>
- string(1) "1"
- [0]=>
- string(1) "1"
- }
- }
果然出来就是字符串了,最后只能自己在插到mongo的时候写了一个小函数,对于数值型字段做了转换,问题就这样解决了。
Tags: yii, mongodb, mysql, string
PHP | 评论:1
| 阅读:17001
Submitted by gouki on 2012, August 8, 9:54 PM
一不小心又把数据库折腾挂了。你妹啊。我只是移动了一点文件,居然就直接挂了,无法启动
再启动的时候,居然直接说。。。mysql启动文件找不到了。什么mysqld_safe之类都在。就是没有mysql。。。
当时心里就郁闷了。用repair修复的时候说。。。plugin表没权限 又说host表没权限 .
苦。最后在vampire的帮助下才搞定了。
苦。
Tags: mysql
DataBase | 评论:0
| 阅读:13076
Submitted by gouki on 2012, July 10, 9:11 AM
我知道INNODB不錯,但是我的VPS只有小小的512M內存,實在是扛不住,這玩意啥也不錯就吃掉了我不少內存了。於是我直接在my.cnf裏加上了skip-innodb。結果服務無法啟動。
找了一下資料 ,原來mysql 5.5以上的時候,默認的引擎就是innodB,因此,如果要skip掉它,必須告訴 mysql我的默認引擎是myisam。因此代碼就變成了這樣,在[mysqld]中加入:
default-storage-engine = MyISAM
然後再skip-innodb,接著運行service mysql restart,世界清靜 了。
原來運行top的時候,mysql一直佔有著70%左右的CPU。現在立刻清零。
一下子安逸了
Tags: linux, mysql, innodb, myisam
Linux | 评论:0
| 阅读:15760