高性能可扩展mysql 笔记(二)用户模型设计、用户实体表结构设计、设计范式
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
一、用户模型设计
电商羡慕中用户模型的设计涉及以下几个部分:

以电商平台京东的登录、注册页面作为例:

用户的基本模块涉及用户的账户名、密码、以及手机号码、所在地等信息。

由个人后台信息截图可知,用户的实体信息其实很多,不仅仅是当前页面所看到的,如下图:

二、用户实体属性的CRUD操作的问题分析
1、当我们确定了需要保存用户的属性后,就需要考虑怎么将属性存到表中了?同时还要考虑保存数据时的一些问题以及优劣性分析!

在将数据进行保存操作时会出现如下几个问题:
1、数据插入异常
PK : 用户登录名
用户表 :{登录名 ... ... 会员级别,级别积分上限,级别积分下线}
insert into 用户表(会员级别)values(`青铜`);
2、数据更新异常
要修改某一行的值时,不得不修改多行数据
例: 用户等级: 青铜级 —> 注册会员
update 用户表 set 等级= `注册会员` where 等级= `青铜级`
3、数据删除异常
删除某一数据时不得不同时删除另一数据
例: 如何删除用户等级名为青铜的等级
delete from 用户表 where 用户等级=`青铜`;
4、数据存在冗余
5、数据表过宽,会影响修改表结构的效率
三、用户实体属性的操作问题的解决方式
遵守数据库的设计方式:
- 设计方式是数据库设计的规范
- 有多种设计范式,如数据库设计第一范式,第二范式和第三范式
- 数据库设计最低要满足第三范式的要求
1、第三范式(3NF)的定义
一个表中的列和其他列之间既不包括部分函数依赖关系,也不包括传递函数依赖关系,那么这个表的设计就符合第三范式。
2、根据第三范式(3NF)优化拆分用户表

这里根据范式将第一张表中的会员级别、级别积分上限、级别积分下线进行拆分成一个小表,因为用户的个人信息修改的频率不高,而用户的级别可能随着时间、经验值等的提升而经常变动,单独拆分出来可以避免对冷数据的重复检索、节约IO资源。

3、根据第三范式设计好的表如下:
用户登录表(customer_login)
DROP TABLE IF EXISTS `customer_login`;
CREATE TABLE `customer_login` (
`customer_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`login_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户登录名',
`password` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'md5加密的密码',
`user_stats` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户状态',
`modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk COMMENT='用户登录表';
用户信息表(customer_inf)
create table customer.customer_inf(
customer_inf_id int unsigned auto_increment not NULL comment '自增主键ID',
customer_id int unsigned not null comment 'customer_login表的自增ID',
customer_name varchar(20) not null COMMENT '用户真实姓名',
identity_card_type TINYINT not null default 1 COMMENT '证件类型:1身份证,2军官证,3护照',
identity_card_no varchar(20) comment '证件号码',
mobile_phone int unsigned comment '手机号',
customer_email varchar(50) COMMENT '邮件',
gender char(1) comment '性别',
user_point int not null DEFAULT 0 COMMENT '用户积分',
register_time TIMESTAMP not null COMMENT '注册事件',
birthday datetime COMMENT '会员生日',
customer_level tinyint not null DEFAULT 1 COMMENT '会员级别:1普通会员,2青铜会员,3白银会员,4黄金会员,5钻石会员',
user_money decimal(8,2) not null default 0.00 COMMENT '用户余额',
modified_time TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP
on update CURRENT_TIMESTAMP COMMENT '最后修改时间',
primary key pk_customerinfid (customer_inf_id)
) engine=innodb comment '用户信息表'
;
用户级别表(customer_level_inf)
create table customer_level_inf(
customer_level TINYINT not null auto_increment COMMENT '会员级别ID',
level_name varchar(10) not null comment '会员级别名称',
min_point int unsigned not null default 0 comment '该级别最低积分',
max_point int unsigned not null DEFAULT 0 COMMENT '该级别最高积分',
modified_time TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP
on update CURRENT_TIMESTAMP comment '最后修改时间',
PRIMARY key pk_levelid (customer_level)
) engine=innodb comment '用户级别信息表'
;
用户地址表 (customer_addr)
create table customer_addr (
customer_addr_id int UNSIGNED auto_increment
not null comment '自增主键ID',
customer_id int UNSIGNED not null COMMENT 'customer_login表的自增ID',
zip smallint not null comment '邮编',
province smallint not null comment '地区表中省份的id',
city smallint not null comment '地区表中城市的id',
district smallint not null comment '地区表中的区id',
address varchar(200) not null comment '具体的地址门牌号',
is_default TINYINT not null comment '是否默认',
modified_time TIMESTAMP not null default CURRENT_TIMESTAMP
on update CURRENT_TIMESTAMP comment '最后修改时间',
PRIMARY key pk_customeraddid(customer_addr_id)
) engine=innodb comment '用户地址表'
;
用户积分日志表(customer_point_log)
create table customer_point_log(
point_id int UNSIGNED not null auto_increment comment '积分日志ID',
customer_id int UNSIGNED not null comment '用户ID',
source tinyint unsigned not null comment '积分来源:0订单,1登录,2活动',
refer_number int unsigned not null default 0 comment '积分来源相关编号',
change_point SMALLINT not null default 0 comment '变更积分数',
create_time TIMESTAMP not null comment '积分日志生成时间',
PRIMARY key pk_pointid(point_id)
) engine=innodb comment '用户积分日志表'
;
用户余额变动表(customer_balance_log)
create table customer_balance_log(
balance_id int UNSIGNED not null auto_increment comment '余额日志id',
customer_id int UNSIGNED not null comment '用户ID',
source TINYINT UNSIGNED not null DEFAULT 1 COMMENT '记录来源:1订单,2退货单',
source_sn int UNSIGNED not null COMMENT '相关单据ID',
create_time TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP COMMENT '记录生成时间',
amount decimal(8,2) not null DEFAULT 0.00 comment '变动金额',
PRIMARY key pk_balanceid(balance_id)
) ENGINE=INNODB COMMENT '用户余额变动表'
;
用户登录日志表(customer_login_log)
create table customer_login_log(
login_id int UNSIGNED not null auto_increment comment '登录日志ID',
customer_id int UNSIGNED not null COMMENT '登录用户ID',
login_time TIMESTAMP not null COMMENT '用户登录时间',
login_ip int unsigned not null COMMENT '登录IP',
login_type TINYINT not null COMMENT '登录类型:0未成功 1成功',
PRIMARY key pk_loginid (login_id)
) ENGINE=INNODB COMMENT '用户登录日志表'
;
高性能可扩展mysql 笔记(二)用户模型设计、用户实体表结构设计、设计范式的更多相关文章
- 高性能可扩展mysql 笔记(一)数据库表、索引、SQL语句设计规范
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 项目说明:该笔记的背景为电商平台项目,电商项目由于其高并发.多线程.高耗能等特性,在众多的项目类型中涉及 ...
- 高性能可扩展mysql 笔记(六) SQL执行计划及分页查询优化、分区键统计
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 常见业务处理 一.使用数据库处理常见业务: 案例: 如何对评论进行分页展示 使用 EXPLAIN 获得s ...
- 高性能可扩展mysql 笔记(四)项目分区表演示
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 登录日志的分区 如何为Customer_login_log表分区? 从以下两个业务场景入手: 用户每次登 ...
- 高性能可扩展mysql 笔记(五)商品实体、订单实体、DB规划
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.商品模块 商品实体信息所存储的表包括: 品牌信息表: create table `brand_i ...
- 高性能可扩展mysql 笔记(三)Hash分区、RANGE分区、LIST分区
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.MySQL分区表操作 1.定义:数据库表分区是数据库基本设计规范之一,分区表在物理上表现为多个文件, ...
- Mysql 笔记二
Mysql 笔记二 Mysql 笔记二 Table of Contents 1. 前言 2. Master Thread 工作方式 2.1. 主循环(loop) 2.2. 后台循(backgroup ...
- MySql笔记(二)
目录 MySQL笔记(二) 一幅画,一次瞬间的回眸,就在那次画展上,那个眼神,温柔的流转,还是那干净的皮鞋,一尘不染,俊朗的眉宇性感的唇,悄悄走近,牵手一段浪漫 MySQL笔记(二) 13.条件查询 ...
- MySql笔记二:命令简介
从笔记二开始讲解一些简单的命令,这些我在SQL Server里面都讲过了,什么主键,约束啥的数据库这些都是相通的,所以MySql这里,不讲,粗略过一遍. 使用命令框登录MySql mysql -u r ...
- MySQL笔记二
Ø function 函数 函数的作用比较大,一般多用在select查询语句和where条件语句之后.按照函数返回的结果, 可以分为:多行函数和单行函数:所谓的单行函数就是将每条数据进行独立的计算,然 ...
随机推荐
- search(10)- elastic4s-multi_match:多字段全文搜索
在全文搜索中我们常常会在多个字段中匹配同一个查询条件或者在不同的字段中匹配不同的条件.比如下面这个例子: GET /books/_search { "query": { " ...
- java1.8新特性之stream
什么是Stream? Stream字面意思是流,在java中是指一个来自数据源的元素队列并支持聚合操作,存在于java.util包中,又或者说是能应用在一组元素上一次执行的操作序列.(stream是一 ...
- 设计模式之GOF23工厂模式02
抽象工厂模式 不能添加单个产品,产品族 public interface Seat { void anmo();}class GoodSeat implements Seat { @Override ...
- [hdu4609]计数方法,FFT
题目:给一个数组a,从里面任选三个数,求以这三个数为三条边能构成三角形的概率. 思路:由于每个数只能用一次,所以考虑枚举三边中的最大边.先将a数组排序,然后枚举它的每个数x作为最大边,那么问题就是要求 ...
- dede文章列表根据权重自定义排序
首先在这里说明一下,网上搜索织梦文章列表自定义的方式无非有以下几种: 1.修改配置文件,新增一个orderid字段,想法很好,但是!但是!!!可能是早期版本的缘故,不适合现在的v5.7系统!按照网上说 ...
- SpringBoot 整合SpringBatch实际项目改造
SpringBoot整合SpringBatch项目,已将代码开源至github,访问地址:https://github.com/cmlbeliever/SpringBatch 欢迎star or fo ...
- Js调用Android回调处理
通常在混合app中经常会使用js调用native的方法,一般是: window.nativeApp.call(XXX); 直接调用native方法,对于简单的处理倒是可以,如果需要回调呢?期待的方式是 ...
- java基础序--列化和反序列化
一.什么是序列化和反序列化: 序列化:是指把java堆内存中的对象转换成字节(二进制流)的过程.也就是通过某种方式将java对象存储在磁盘内存中,这个过程称为序列化 反序列化:是把磁盘上的对象转恢复成 ...
- kudu_遇到的一些问题
最近在研究,自己搭建kudu遇到的一些问题,及解决方法,供大家参考. 1.java连接kudu,出现超时的问题,是因为kudu开启了认证模式: 通过查找 ...
- JS 把数字转换成字母
JS 把数字转换成字母 2013-03-12 22:28:11 分类: JavaScript String.fromCharCode(addcount+65) 位运算alert(1<<0 ...