双十一RDS最佳实践

同步服务数据库访问规范


5
最佳实践
-
拆分

.
常见误区:将拆分进行到底
1.
我要对一张
2
百万的表进行拆分
2.
只有当主库不能处理写
(DML)
负载的时候,需要进行拆分
3.
拆分对应用增加了复杂度
4.
分区是比较安全和简单的拆分
5.
读较多的应用可以进行读写分离
6.
不是所有的应用都能进行拆分

.
保持简单的架构
1.
不是所有的应用都像淘宝一样的
2.
过于复杂的架构你是否有能力进行掌控
3.
简单的架构给你的优化带来便利
6
最佳实践
-
拆分
.
单实例
RDS
容量有限,业务在不断发展,应用压力越来越大。如何解决?
.
想设计一个高可扩展的系统,关系数据库的扩展如何解决?
.
分布式
RDS
是什么?
数据访问中间件
MySQL
协议,支持各种编程语言
帮助用户做水平拆分
7
最佳实践
-
拆分
拆分
--
最佳实践
绝大多数的应用不需要分库分表
保持简单应用架构
先优化,在考虑拆分
优先考虑垂直拆分,在水平拆分
DRDS
帮助你解决水平拆分的难题
8
最佳实践
-
性能优化

.
分页优化:
小东
(2013-06-05 18:29:38):
这个可能是什么问题呀。
玄惭
(21:42:13):
iops
超了
小东
(21:42:31):
嗯嗯

这个
sql
写的看来有问题。
|
Query | 51 | Sending data
|
select id,
...
from t_buyer where sellerId = 765922982
and gmt_modified >= '1970-01-01 08:00:00'
and gmt_modified <= '2013-06-05 17:11:31'
limit 255000, 5000
9
最佳实践
-
性能优化

.
分页优化:
玄惭
(21:46:24):
select t2.
*
from
(select id from t_buyer where sellerId = 765922982
and gmt_modified >= '1970-01-01 08:00:00'
and gmt_modified <= '2013-06-05 17:11:31'
limit 255000, 5000

t1,t_buyer t2 where t1.id=t2.id
小东
(21:46:49):
这样为啥会快呀,玄惭,
玄惭
(21:47:00):
你先试一试吧
小东
(21:58:43):
好像很快啊。神奇,这个原理是啥啊。
牛!!!
小东
(21:59:55):
5000 rows in set (4.25 sec)
前面要
90
秒。
index

seller_id,gmt_modified
10
最佳实践
-
性能优化

.
分页优化
--
最佳实践
普通
limit M

N
的翻页写法,往往在越往后翻页的过程中速度越慢,原因
mysql
会读取表中的前
M+N
条数据,
M
越大,性能就越差,
select
*
from t where sellerid=100 limit 100000

20
优化后的翻页写法,先查询翻页中需要的
N
条数据的主键
id
,在根据主键
id
回表查询所需要的
N
条数据,此过程中查询
N
条数据的主键
ID
在索引中完成
select t2.
*
from t t1,(select id from t sellerid=100 limit 100000

20) t2
where t1.id=t2.id;
t
表中的索引:
sellerid
字段上创建索引
11
最佳实践
-
性能优化

.Order by COL desc/asc limit N
SELECT o.
*
FROM order_info o WHERE
is_send=0 AND o.order_status in (0,1) AND
o.shipping_status = 0
AND o.is_separate > 0 and o.jhd_id=0 group by o.order_id
ORDER BY o.add_time DESC LIMIT 20
mysql> explain
SELECT o.
*
FROM order_info o WHERE
is_send=0 AND o.order_status in (0,1) AND
o.shipping_status = 0
AND o.is_separate > 0 and o.jhd_id=0 group by o.order_id
ORDER BY o.add_time DESC LIMIT 20
\G;
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
1. row
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
id: 1
select_type: SIMPLE
table: o
type: index_merge
possible_keys: order_status,shipping_status,is_send,is_separate
key: shipping_status,is_send
key_len: 1,2
ref: NULL
rows: 146393
Extra: Using intersect(shipping_status,is_send); Using where; Using filesort
1 row in set (0.00 sec)
执行时间
:20 rows in set (21.00 sec)
12
最佳实践
-
性能优化

.Order by COL desc/asc limit N

mysql> explain SELECT o.
*
FROM order_info o WHERE is_send=0 AND o.order_status in (0,1) AND
o.shipping_status = 0 AND o.is_separate > 0 and o.jhd_id=0 group by o.order_id
ORDER BY o.add_time DESC LIMIT 20\G;
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
1. row
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
id: 1
select_type: SIMPLE
table: o
type: index
possible_keys: order_status,ind_order_info_status,ind_order_info_shiiping_status
key: add_time_1
key_len: 779
ref: NULL
rows: 4993
Extra: Using where
1 row in set (0.00 sec)
执行时间
:20 rows in set (0.00 sec)
13
最佳实践
-
性能优化

.Order by COL desc/asc limit N--
最佳实践
在上述特点的查询中,如果
mysql
查询数据的顺序与
order by
的字段一致的,
也就是说在排序字段上有索引,
mysql
沿着索引的顺序读取下来,当满足了
查询中
N
条记录,则立刻返回查询。
sellerid
gmt_create
100
20:00
101
22:01
101
22:07
101
22:33
....
....
....
....
101
23:00
102
21:00
100w
select
*
from order where sellerid=101 and ........
order by gmt_create limit 10
查询到满足
10
条结果集查询结束
14
最佳实践
-
性能优化

.
根据过滤性创建索引:
hhysc (2013-06-05 16:37:58):
SELECT
*
FROM
`efast`.`order_info`
WHERE
lylx IN (2, 15)
AND (
(dist_type = 0)
OR (dist_type = 1 AND rj = 2)
OR (dist_type = 2 AND rj = 2)
)
AND order_status = 1
AND is_send = 0
ORDER BY shipping_time, pay_time, add_time ASC
这种
SQL
能优化的不?
3

order by
字段
这个也是很慢的一个
SQL
,但是是主流程上面要用到的
玄惭
(2013-06-05 16:43:49):
可以
15
最佳实践
-
性能优化

.
根据过滤性创建索引:
玄惭
(2013-06-05 16:43:49):
可以
mysql> select count(
*
) from order_info where lylx IN (2, 15) AND order_status = 1 ;
+----------+
| count(
*
) |
+----------+
| 12361 |
+----------+
1 row in set (0.01 sec)
mysql> select count(
*
) from order_info where lylx IN (2, 15) AND is_send = 0;
+----------+
| count(
*
) |
+----------+
| 2548 |
+----------+
1 row in set (0.00 sec)
mysql> select count(
*
) from order_info where lylx IN (2, 15) AND order_status = 1 AND is_send = 0;
+----------+
| count(
*
) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
16
最佳实践
-
性能优化

.
根据过滤性创建索引:
mysql> alter table order_info add index ind_order_info_lylx(lylx,order_status,is_send);
mysql> SELECT
*
FROM `efast`.`order_info` WHERE lylx IN (2, 15) AND
( (dist_type = 0) OR (dist_type = 1 AND rj = 2) OR (dist_type = 2 AND rj = 2) )
AND order_status = 1 AND is_send = 0 ORDER BY shipping_time, pay_time, add_time;
Empty set (0.00 sec)
你看看速度吧
hhysc (2013-06-05 16:46:10):
这下很快了
17
最佳实践
-
性能优化

.
根据过滤性创建索引
--
最佳实践
1.
创建索引的时候,优先将过滤性高的查询字段放在首位;
2.mysql
的索引有前导列的限制,优先将等值的条件的字段放在
索引顺序的前列;
3.
若有
>,<,not in,between,!=
的查询条件的字段加入索引列后,
后续加入的索引字段都不能起到过滤作用;