导数据中学到的几点东西

1. mysql 的查询速度可能受mysql qcache的影响,更可能受系统cache的影响,而且系统cache影响可能是200和6000的差别,不可小视啊。

2. 如果能批量处理就不要一条一条地处理,批量处理方法:

a.  mysqldump 工具
b.  select * into outfile "myfile" from atable;  // 这样将以tab分隔的方式将记录写到文件里面,对于反斜线会自动加反斜线转义的
c.  用loaddata将b的结果导入到目标表里面

3. mysql的瓶颈一般在磁盘IO上
4. 不要小看sql语句的优化,注意下面两条语句的区别

a.  select * from atable where akey = ‘avalue’;
b.  select count(*) from atable where akey = ‘avalue’;

这里不仅仅是结果集的数据量的差异,a语句除了访问索引文件,还要访问数据文件; 而b语句只访问索引文件就够了; 如果内存小的话,这里的差异就比较大了。

5.  mysql 需要修改表结构时的一些到数据的问题

a. 首先考虑上面提到的使用文件的方式处理
b. 如果需要逐条数据处理则可以将源数据导成文本文件,逐行处理; 注意: 数据要干净,否则就不要使用文件处理
c. 如果需要逐条处理,但是数据量很大,又不能一次查询获取,一般的做法为:
   按照主键排序,每次取一部分(如:1万条,和每条数据量大小有关,既不要频繁获取,又不要每次获取数据量太大,以至于占太多内存)
   这种做法似乎很常用,但是
   写程序并不简单,需要考虑的地方比较多;
   排序只是为了将数据分块,所以做了一些无用功;
   排序是一件很耗时的事情,如果数据量很大,非常不建议使用order by;
   排序还很可能出现[ERROR] /usr/local/mysql/libexec/mysqld: Sort aborted 的错误
   下面介绍一种比较简单有效的做法:
   思路是我们只是想把要取的数据分块儿,很自然就想到了hash,如果主键(的一)部分是数字,则可以根据数量的大小选取一个适当的素数,根据对该素数取模来分块; 将设有900万条数据,每次想取约1万条,则 900万/1万 = 100 ,则取100左右的素数就行,如:127;
   如果主键不是数字,也可以使用hash函数
   


6.  联合主键时的一些查询

mysql> select sql_no_cache count(*) into outfile "/tmp/a" from t_user_friend_list_52 group by user_
id;
Query OK, 878180 rows affected (6.65 sec)

mysql> select sql_no_cache count(*) into outfile "/tmp/b" from t_user_friend_list_52 group by user_
id,friend_id;
Query OK, 9511565 rows affected (10.48 sec)

mysql> select sql_no_cache * into outfile "/tmp/c" from t_user_friend_list_52 order by user_id,frie
nd_id limit 9000000,1000;         
Query OK, 1000 rows affected (31.82 sec)

mysql> select sql_no_cache * into outfile "/tmp/d" from t_user_friend_list_52 order by user_id limi
t 9000000,1000;         
Query OK, 1000 rows affected (31.96 sec)

前两行比较说明根据联合主键的第一列分组还是比根据整个联合主键分组要快一些,毕竟都是只访问索引文件
后两行比较说明根据联合主键的第一列排序还是比根据整个联合主键排序没有明显差别

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据