MySQL分库分表分表后数据的查询(5th)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

前言

在分表完之后显然对于数据的查询会变的比较的复杂,特别是在表的关联方面,在有些情况下根本就不能使用JOIN。

其实个人是比较鼓励将那些大的JOIN SQL拆分成几个小的SQL来查询数据。这样虽然总体的效率可能会稍稍下降(如果使用了连接池完全可以忽略),但是查询的语句变简单了,使得后续的维护带来的方便。同时也能带来比较便利的扩展。你可以感受一下有一个100行的SQL语句给你维护,和给你10个10行并且每一块都有很好的注释的SQL去维护,去帮助调优。你愿意选哪个。不管你们信不信,反正我是选第二种,而且第二种可以很好的理解业务。

上面说到要拆分JOIN,我的意思不是将每个语句都拆分。我的准则是 O(n) 次的查询。忌讳那种查出数据后通过程序循环查出结果再去数据库中查询,也就是需要 O(n*M)这种。 瞬间感觉方法论很重要有木有 ^_^。

模拟场景

  • 场景1:购买者下订单

1、在浏览商品的时候能获得商品的 门店ID 和 商品ID,至于导购ID这里我们能以随机的形式得到(需要根据业务来确定如何获取导购ID)

2、通过导购ID获得导购的用户信息从而得到导购的数据应该放在那张分表。

3、将下单数据存入出售者的分表,和购买者的分表。

下面展示的是伪代码(因为只用SQL不好展示具体业务逻辑),其实是自己比较懒不想写Python了。^_^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 获得导购分表信息,和所在门店
SELECT  u.table_flag  AS  guide_flag,
   ug.store_id  AS  store_id
FROM  user  AS  u, user_guide  AS  ug
WHERE  u.user_id = ug.user_id
   AND  user_guide_id = 导购ID;
  
SET  autocommit=0;
START  TRANSACTION ;
-- 创建销售订单 sell_order_2 通过程序拼凑出来的
INSERT  INTO  sell_order_2
VALUES (order_SnowflakeID, 导购ID, 购买者ID, 订单总额, 订单状态);
-- 记录此订单有哪些商品
INSERT  INTO  order_goods_2
VALUES (order_goods_SnowflakeID, order_SnowflakeID, 商品ID, 商品价格, 商品个数);
-- 记录购买订单表  buy_order_6 购买者所在的分表,上面的是出售者所在的分表别弄混了
-- 购买者订单ID 和 出售者订单ID是一样的
INSERT  INTO  buy_order_6
VALUES (order_SnowflakeID, 用户ID, 导购ID)
  
COMMIT ;
SET  autocommit=1;
  • 情况2:购买者浏览订单

浏览购买者订单就是比较麻烦的,因为购买者订单信息和商品信息不是在同一分表中。

1、分页查找出购买者的订单列表。

2、将订单信息返回给浏览器后,使用ajax获取每个订单的商品。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- 获得用户的分表信息 user_id = 66
SELECT  table_flag  FROM  user  WHERE  user_id=66;
+ ------------+
| table_flag |
+ ------------+
|          9 |
+ ------------+
-- 获取用户订单, 这些信息值直接先返回给浏览器的
SELECT  FROM  buy_order_9  WHERE  user_id=66 LIMIT 0, 1;
+ ---------------------+---------+---------------+
| buy_order_id        | user_id | user_guide_id |
+ ---------------------+---------+---------------+
| 3792111966815784961 |      66 |             1 |
+ ---------------------+---------+---------------+
-- 获取 user_guide_id=1 用户的分表信息
SELECT  u.table_flag  AS  guide_flag
FROM  user  AS  u, user_guide  AS  ug
WHERE  u.user_id = ug.user_id
   AND  user_guide_id = 1;
+ ------------+
| guide_flag |
+ ------------+
|          2 |
+ ------------+
-- 浏览器通过ajax获取商品信息进行展现
SELECT 
FROM  order_goods_2 
WHERE  sell_order_id = 3792111966815784961
   AND  user_guide_id = 1;
+ ---------------------+---------------------+---------------------+---------------+---------+------+
| order_goods_id      | sell_order_id       | goods_id            | user_guide_id | price   | num  |
+ ---------------------+---------------------+---------------------+---------------+---------+------+
| 3792112143781859329 | 3792111966815784961 | 3792111950445416449 |             1 | 3100.00 |    2 |
| 3792112160789762049 | 3792111966815784961 | 3792111951305248769 |             1 | 5810.00 |    1 |
+ ---------------------+---------------------+---------------------+---------------+---------+------+

从上面的试验我们可以看到原本在 '分库分表(1)--基础表介绍' 中的关联查询就能获得出订单的数据现在需要被拆为多个部分来查询(是不可避免的, 这样做也未必不是好事)。

 

这里说一下我们为什么要使用ajax来获取并展现 '订单商品' 的数据:

1、我们不知道 '购买订单' 的导购的分表是哪一个,因此我们需要便利查询出的每一条 '购买订单',如果有10个订单就需要便利10次去获取对应导购是哪个分表。

2、获得分表完之后还需要通过每个分表去关联 '订单商品' 获得商品信息。

3、获得到以上信息或需要整合成一个列表返回给浏览器。

通过上面一次性把说有数据返回给浏览器的方法,会影响到用户体验,让用户觉得很慢的感觉。并且需要写复杂的逻辑,难以维护。

我们将查询时间放大,一个查是 1s 如果有10个订单 一次性完成就可能需要 11s 以上的时间才返回给浏览器。如果先将查询的订单返回给浏览器。看上去就只需要 1s就吧数据返回给浏览器了。

  • 情况3:导购查看订单

导购也是一个普通用户, 因此一登陆系统就知道 导购ID 和 用户ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-- 获得导购的分表信息 user_id = 6, user_guide_id = 5
SELECT  table_flag  FROM  user  WHERE  user_id=6;
+ ------------+
| table_flag |
+ ------------+
|          6 |
+ ------------+
-- 查询订单信息
SELECT  FROM  sell_order_6  WHERE  user_guide_id = 5 LIMIT 0, 3;
+ ---------------------+---------------+---------+---------+--------+
| sell_order_id       | user_guide_id | user_id | price   | status |
+ ---------------------+---------------+---------+---------+--------+
| 3792112033412943873 |             5 |      10 | 5197.00 |      1 |
| 3792112033429721089 |             5 |      10 | 6826.00 |      1 |
| 3792112033446498305 |             5 |      10 | 5765.00 |      1 |
+ ---------------------+---------------+---------+---------+--------+
-- 查询订单商品信息
SELECT  FROM  order_goods_6
WHERE  sell_order_id  IN (
   3792112033412943873,
   3792112033429721089,
   3792112033446498305
);
+ ---------------------+---------------------+---------------------+---------------+---------+------+
| order_goods_id      | sell_order_id       | goods_id            | user_guide_id | price   | num  |
+ ---------------------+---------------------+---------------------+---------------+---------+------+
| 3792112273532653569 | 3792112033412943873 | 3792111951800176641 |             5 | 7826.00 |    1 |
| 3792112292964864001 | 3792112033412943873 | 3792111952559345665 |             5 | 3057.00 |    2 |
| 3792112273545236481 | 3792112033429721089 | 3792111952660008961 |             5 | 8540.00 |    1 |
| 3792112292981641217 | 3792112033429721089 | 3792111951863091201 |             5 | 8545.00 |    1 |
| 3792112273566208001 | 3792112033446498305 | 3792111952110555137 |             5 | 8383.00 |    2 |
| 3792112292998418433 | 3792112033446498305 | 3792111952966193153 |             5 | 3282.00 |    2 |
+ ---------------------+---------------------+---------------------+---------------+---------+------+
  • 情况4:导购修改订单

1
2
-- 修改订单价格
UPDATE  sell_order_6  SET  price = 1000.00  WHERE  sell_order_id = 3792112033412943873;
  • 情况5:店主为店铺添加商品

添加商品只有店铺的店主有权限。然而店主也是一个普通用户。

1
2
3
4
5
6
7
8
9
-- 获得店主的分表信息 user_id = 1
SELECT  table_flag  FRO M  user  WHERE  user_id=1;
+ ------------+
| table_flag |
+ ------------+
|          2 |
+ ------------+
-- 店主添加商品
INSERT  INTO  goods_2  VALUES (SnowflakeID, 商品名称, 商品价格, 门店ID);


文章出自:http://www.ttlsa.com/mysql/mysql-distributed-database-and-table-query/








      本文转自027ryan  51CTO博客,原文链接:http://blog.51cto.com/ucode/1746027,如需转载请自行联系原作者

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
缓存 NoSQL 关系型数据库
13- Redis和Mysql如何保证数据⼀致?
该内容讨论了保证Redis和MySQL数据一致性的几种策略。首先提到的两种方法存在不一致风险:先更新MySQL再更新Redis,或先删Redis再更新MySQL。第三种方案是通过MQ异步同步以达到最终一致性,适用于一致性要求较高的场景。项目中根据不同业务需求选择不同方案,如对一致性要求不高的情况不做处理,时效性数据设置过期时间,高一致性需求则使用MQ确保同步,最严格的情况可能涉及分布式事务(如Seata的TCC模式)。
44 6
|
3天前
|
SQL 关系型数据库 MySQL
Spring_jdbc数据连接池(mysql实现增、删、改、查)
Spring_jdbc数据连接池(mysql实现增、删、改、查)
11 0
|
1天前
|
关系型数据库 MySQL 数据挖掘
【MySQL】多表连接查询
【MySQL】多表连接查询
|
4天前
|
存储 数据可视化 关系型数据库
MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%🚀
本文探讨MySQL中时间类型的选择,阐述datetime、timestamp、整形时间戳等类型特点以及它们在千万级数据量下的查询性能
MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%🚀
|
9天前
|
SQL 关系型数据库 MySQL
mysql 数据库查询 查询字段用逗号隔开 关联另一个表并显示
mysql 数据库查询 查询字段用逗号隔开 关联另一个表并显示
18 2
|
10天前
|
关系型数据库 MySQL Shell
MySQL 查询
MySQL 查询
|
13天前
|
SQL 关系型数据库 MySQL
DQL语言之基础查询(mysql)
DQL语言之基础查询(mysql)
|
13天前
|
SQL 关系型数据库 MySQL
DQL语言之连接查询(mysql)
DQL语言之连接查询(mysql)
|
13天前
|
关系型数据库 MySQL
MySQL全局库表查询准确定位字段
information_schema.COLUMNS 详细信息查询
202 4
|
17天前
|
关系型数据库 MySQL
Mysql查询语句的执行顺序
Mysql查询语句的执行顺序
12 0