MySQL DBA's Blog

MySQL分页优化(SQL篇)

March 5th, 2010

上文提到可以通过去除跳页和限制翻页来减少整个系统的压力。然而PD往往会考虑到用户体验,不愿意去推动这种功能上的删减。
家家有本难念的经,可以理解PD的苦衷。那么作为一个DBA,就只能从SQL上去优化分页的性能了。

假设我们有一个需要分页的表,如下:
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` int(11) NOT NULL,
`c` datetime NOT NULL,
`d` varchar(1000) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_b_c` (`b`,`c`),
KEY `idx_b_id` (`b`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
ID为自增,b为随机数,c为递增的时间,d为长度1000的字符串。往里面插入200w+数据。

典型的分页语句如下:
SQL1:select SQL_NO_CACHE * from test force index(idx_b_c) where b=1 order by c desc limit 2000,10
在六块磁盘做RAID10的情况下,SQL1需要耗费6s以上。explain SQL1可以得到以下结果:
+—-+————-+——-+——+—————+———+———+——-+——+————-+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——-+——+—————+———+———+——-+——+————-+
| 1 | SIMPLE | test | ref | idx_b_c | idx_b_c | 4 | const | 2574 | Using where |
+—-+————-+——-+——+—————+———+———+——-+——+————-+
using where表示MySQL从InnoDB获取了数据之后还要根据条件进行筛选,也就是limit 2000,10那部分。 Read the rest of this entry »

MySQL分页优化(功能篇)

March 2nd, 2010

当数据量大到一定程度的时候,用户往往已经无法一次性查看所有数据,于是就产生了分页需求。
纵观百度、腾讯、网易、淘宝等大型互联网公司的产品,分页之处比比皆是。下面是淘宝的评价页面截图:

说实话,淘宝的分页太过于强大,想怎么查看就怎么查看。不加限制的分页功能,会给系统带来极大的压力和隐患。要优化分页,就必须要舍弃一些华而不实的功能。下面就是造成巨大压力的几个祸首:
1、跳页。用户实际上并不知道在哪一页会出现什么样的内容,也就是说用户无法预期自己跳页后将会获得的数据。从这个角度想,跳页是用户的一种不精确行为。假设某用户查询了2009-01-01到2010-01-01的数据,他在翻了几页之后突然想起需要查看2009-11-11那一天的评价,于是他就使用了跳页功能。跳到差不多的页数后,他再慢慢向前或者向后翻页。
Read the rest of this entry »

过年了,祝福大家新年快乐!

February 12th, 2010

下午就要离开杭州,坐汽车回温州了,预祝大家有一个幸福的新年~

这个星期远在美国的阿婆(九十岁……)介绍了个美国妞,让我打国际长途去慰问,结果打了好几次没打通。
决定不继续打了,回去爱咋地咋地,大不了被老妈骂过年。都说距离产生美,但是阿凡达干的那事对我而言,还是有点难度的。
昨天有人说我唠叨,为了保持简洁的风格,就不继续唠叨了。

再次祝愿大家新年快乐,阖家美满!

mysqldump意外终止的原因以及解决方法

February 6th, 2010

mysqldump是非常重要的MySQL备份工具。然而在长年累月的使用过程中,TAOBAO多次出现了因mysqldump意外终止而导致备份失败的情况。
以下是我们经常遇到的问题:

1、Lost connection to MySQL server at ‘reading initial communication packet’:
这个主要是因为DNS不稳定导致的。如果做了网络隔离,MySQL处于一个相对安全的网络环境,那么开启skip-name-resolve选项将会最大程度避免这个问题。

2、Lost connection to MySQL server at ‘reading authorization packet’:
从MySQL获取一个可用的连接是多次握手的结果。在多次握手的过程中,网络波动会导致握手失败。增加connect_timeout可以解决这个问题;然而增加connect_timeout并不能防止网络故障的发生,反而会引起MySQL线程占用。最好的解决办法是让mysqldump重新发起连接请求。

3、Lost connection to MySQL server during query:
这个问题具备随机性,而淘宝MySQL的应用场景决定了我们无法多次备份数据以便重现问题。
然而我们注意到这个问题一般会在两种情况下会发生。一种是mysqldump **** | gzip ****;另外一种是mysqldump **** > /nfs-file
注意,不管是gzip还是nfs都有一种特点,那就是它们影响了mysqldump的速度。从这个角度思考,是不是mysqldump从MySQL接受数据包的速度不够快导致Lost connection to MySQL server during query错误呢?
Read the rest of this entry »