手把手教你PolarDB-X中的表设计——用户表
简介: 本系列旨在描述一个具体的业务场景,给出建表的例子,帮助大家更好的使用PolarDB-X。本期的主题是:用户表。
本系列旨在描述一个具体的业务场景,给出建表的例子,帮助大家更好的使用PolarDB-X。本期的主题是:用户表。
需求描述
大多业务都会有一张用户表,用来存用户的数据,例如这样一张用户表:
user_id bigint AUTO_INCREMENT,
user_name varchar(64),
mobile_phone varchar(64),
email varchar(64),
enc_password varchar(256),
address varchar(128),
other_info1 varchar(128),
other_info2 varchar(128),
PRIMARY KEY (user_id)
)
对这张表,一般会有以下几种业务操作:
● 注册,特点是要保证用户名、手机号、邮箱等唯一:
INSERT INTO users VALUES (?, ?, ?)
● 登录,现在大多数APP都支持手机号、邮箱地址、用户名等多个维度进行登录,所以会有多种类型的SQL:
//按照用户名(user_name)进行登录:
SELECT *
FROM users
WHERE user_name = ?;
//按照手机号(mobile_phone)进行登录:
SELECT *
FROM users
WHERE mobile_phone = ?;
//按照邮箱(email)进行登录:
SELECT *
FROM users
WHERE email = ?;
● 登录后,系统内一般会使用用户ID(user_id)查询或者更新用户信息:
SELECT *
FROM users
WHERE user_id = ?;
UPDATE users
SET xxxx = ?
WHERE user_id = ?;
对于这样的一张表,我们在PolarDB-X中该如何设计呢?
这里我们根据数据库的MODE(PolarDB-X中数据库的MODE参数:https://help.aliyun.com/document_detail/416411.html),给出两种示例:
DRDS模式
在DRDS模式的数据库中,我们需要设计表的分区键。
users表的查询条件有user_id、user_name、mobile_phone、email,这四种条件的查询的量都差不多,都属于在线类查询。对于传统的分库分表中间件来说,一个表的分区键只能选择一个,那么无论选择哪一个做分区键,对于其他三个条件的查询,都会是一场灾难。
PolarDB-X支持全局索引(什么是全局索引:https://zhuanlan.zhihu.com/p/395415647),那这个问题就很好解决了,我们按照下面语句建表即可:
CREATE DATABASE drds_test MODE='drds';
use drds_test;
CREATE TABLE users (
user_id bigint AUTO_INCREMENT,
user_name varchar(64),
mobile_phone varchar(64),
email varchar(64),
enc_password varchar(256),
address varchar(128),
other_info1 varchar(128),
other_info2 varchar(128),
PRIMARY KEY (user_id)
) DBPARTITION BY HASH(user_id);
CREATE GLOBAL UNIQUE INDEX gsi_users_user_name ON users (user_name) DBPARTITION BY HASH(user_name);
CREATE GLOBAL UNIQUE INDEX gsi_users_mobile_phone ON users (mobile_phone) DBPARTITION BY HASH(mobile_phone);
CREATE GLOBAL UNIQUE INDEX gsi_users_email ON users (email) DBPARTITION BY HASH(email);
这样,我们在user_name、mobile_phone、email上分别创建了三个全局唯一索引。对于上述的查询SQL,每一种都会非常的高效。同时,也会保证注册场景下的唯一性。
当然,这些创建索引的语句也可以直接合并在建表语句中,相关语法参考:https://help.aliyun.com/document_detail/316584.html:
DROP TABLE users;
CREATE TABLE users (
user_id bigint AUTO_INCREMENT,
user_name varchar(64),
mobile_phone varchar(64),
email varchar(64),
enc_password varchar(256),
address varchar(128),
other_info1 varchar(128),
other_info2 varchar(128),
PRIMARY KEY (user_id),
UNIQUE GLOBAL KEY gsi_users_email (email) DBPARTITION BY HASH(email),
UNIQUE GLOBAL KEY gsi_users_mobile_phone (mobile_phone) DBPARTITION BY HASH(mobile_phone),
UNIQUE GLOBAL KEY gsi_users_user_name (user_name) DBPARTITION BY HASH(user_name)
) DBPARTITION BY hash(user_id);
此外,如果想进一步提升查询的性能,避免全局索引回表的代价,还可以把全局索引创建为全局聚簇索引。这样会消耗更多的空间,但查询性能会更高。例如:
CREATE GLOBAL CLUSTERED UNIQUE INDEX gsi_clustered_users_user_name ON users (user_name) DBPARTITION BY HASH(user_name);
注意:上述用法对于PolarDB-X 1.0(version >= 5.4.12)也同样适用。
AUTO模式
对于AUTO模式,则无需关注分区键等信息,像在MySQL中建表即可:
CREATE DATABASE auto_test MODE='auto';
use auto_test;
CREATE TABLE users(
user_id bigint auto_increment,
user_name varchar(64),
mobile_phone varchar(64),
email varchar(64),
enc_password varchar(256),
address varchar(128),
other_info1 varchar(128),
other_info2 varchar(128),
PRIMARY KEY(user_id),
UNIQUE KEY uk_user_name(user_name),
UNIQUE KEY uk_mobile_phone(mobile_phone),
UNIQUE KEY uk_email(email)
);
同样的能达到和手动分区一样的效果。
我们可以使用EXPLAIN语句来查看一下执行计划:
EXPLAIN SELECT * FROM users WHERE mobile_phone = 1;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| LOGICAL EXECUTIONPLAN |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Project(user_id="user_id", user_name="user_name", mobile_phone="mobile_phone", email="email", enc_password="enc_password", address="address", other_info1="other_info1", other_info2="other_info2") |
| BKAJoin(condition="user_id = user_id", type="inner") |
| IndexScan(tables="uk_mobile_phone_$1ace[p16]", sql="SELECT `user_id`, `mobile_phone` FROM `uk_mobile_phone_$1ace` AS `uk_mobile_phone_$1ace` WHERE (`mobile_phone` = ?)") |
| Gather(concurrent=true) |
| LogicalView(tables="users[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `user_id`, `user_name`, `email`, `enc_password`, `address`, `other_info1`, `other_info2` FROM `users` AS `users` WHERE ((`mobile_phone` = ?) AND (`user_id` IN (...)))") |
| HitCache:false |
| Source:PLAN_CACHE |
| TemplateId: beaaba3a |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
8 rows in set (0.32 sec)
可以看到,这个SQL会正确的使用索引来进行查询,而不会进行全表扫描。
测试环境
以上示例均在阿里云公共云PolarDB-X 2.0 5.4.13-16462728验证通过。
本文作者:梦实
本文来源:PolarDB-X 知乎号
手把手教你PolarDB-X中的表设计——用户表的更多相关文章
- 手把手教你写Sublime中的Snippet
手把手教你写Sublime中的Snippet Sublime Text号称最性感的编辑器, 并且越来越多人使用, 美观, 高效 关于如何使用Sublime text可以参考我的另一篇文章, 相信你会喜 ...
- orale数据库.实例.表空间.用户.表
近期因为工作原因接触到Oracle数据库.了解到Oracle和mysql的结构上还是有很大的区别的. Oracle数据库---实例---表空间---用户---表 我们将从这5个方面来了解Oracle ...
- 第三百七十三节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
第三百七十三节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表.验证码表.轮播图表 创建Django项目 项目 settings.py ...
- Oracle中查看所有的表,用户表,列名,主键,外键
在Oracle中查看所有的表: select * from tab/dba_tables/dba_objects/cat; 看用户建立的表 : select table_name from user_ ...
- SQL Server 中获取所有的用户表、用户视图的信息
直接贴代码了: 用户表: SELECT s.Name,Convert(varchar(max),tbp.value) as Description FROM sysobjects s AND (tbp ...
- mysql设计与优化以及数据库表设计与表开发规范
一.设计问题? 1.主键是用自增还是UUID ? Innodb 中的主键是聚簇索引. 如果主键是自增的,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的 ...
- oracle习题练习-表空间-用户-表-约束
题一 1. 创建名字为hy_tablespace的表空间,默认大小为10M;@@ 2. 创建一个用户,用户名以自己名字命名,并指定命名空间为hy_tablespace;@@@@ ...
- MySQL进阶:约束,多表设计,多表查询,视图,数据库备份与还原
MySQL进阶 知识点梳理 一.约束 1. 外键约束 为什么要有外键约束 例如:一个user表,一个orderlist 如果现在想要直接删除id为1的张三,但是orderlist里还有用户id为1的订 ...
- 手把手教你在VirtualBox中与主机共享文件夹
安装VirtualBox为了共享文件夹,折腾了一晚上!网上的很多资料都不是很全面,这里就全面的总结一下,如果有其他的疑问,可以留言多多交流. VirtualBox下载地址,版本为5.1.2 设置共享文 ...
- 小姐姐手把手教你JS数组中的对象去重
有时候数据库中的数据重复的,我们另一个需求需要数据的唯一性 那么这时候就用到这个方法了 我还是以截图的方式发粗来 不然太丑了 见谅 console.log(map)打印出来的结果已经帮我们把需要的 ...
随机推荐
- AAC音频编码之--概念介绍
一 概念 AAC,全称Advanced Audio Coding,是一种专为声音数据设计的文件压缩格式.与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的"性价比".利 ...
- KTL 一个支持C++14编辑公式的K线技术工具平台
K,K线,Candle蜡烛图. T,技术分析,工具平台 L,公式Language语言使用c++14,Lite小巧简易. 项目仓库:https://github.com/bbqz007/KTL 国内仓库 ...
- 逆向通达信Level-2 续五 (调试窗口层次结构)
演示 hierarchy, checkCWnd命令. 窗口层次结构向上追溯寻根.自动识别是否为CWnd对象,并且自动搜索对象指针. 窗口层次结构内容包括: 1.窗口类名 2.窗口实现所在模块 3.窗口 ...
- 35_音视频播放器_seek&暂停
目录 一.实现seek功能 二.解决点击seek操作时会出现画面快速闪过 三.实现暂停功能 3.1.音频暂停 3.2.视频暂停 一.实现seek功能 我们主要是使用ffmpeg的av_seek_fra ...
- 之字形打印二叉树—Java
给定一颗二叉树,逐层打印,并且每层打印的方向是不一样的,比如: 逐层打印的结果是:1 3 2 4 5 6 8 7 代码: import java.util.ArrayList; import java ...
- [极客大挑战 2019]web部分题解(已完结!)
SQL部分: [极客大挑战 2019]BabySQL 打开环境后有登录界面◕‿◕ 一眼注入,后先试试万能密码: username:admin' or '1'='1 password:1 GG,出大问题 ...
- Python基于Excel生成矢量图层及属性表信息:ArcPy
本文介绍基于Python中ArcPy模块,读取Excel表格数据并生成带有属性表的矢量要素图层,同时配置该图层的坐标系的方法. 1 任务需求 首先,我们来明确一下本文所需实现的需求. 现有 ...
- 《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南 - 第3章
本章勘误: 暂无,等待细心的你告诉我哦. 本章注解: 暂无 本章释疑: 暂无,等待你的提问 致谢: MVP 林德熙 MVP 吕毅 sPhinX 相关链接 试读记录
- Word文档最后一页空白页中换行符无法删除
Word文档最后一页空白页中换行符无法删除 问题如题: 尝试了delete.backspace.backspace+delete都不行. 找到了这个方法: 选中最后一页的换行符,然后段落--间距--行 ...
- FPGA模块化设计
模块化设计出发点 在实际地操作中,总有一些基础的模块需要不断地寻找,往往需要消耗大量的时间.为了节约模块化设计的时间,提高设计的效率.在这里将一些基础的模块全部进行封装,利用网络的便捷性,实现快速地基 ...