垂直拆分
1. 垂直拆分的定义
所谓的垂直拆分,就是把原来一个有很多列的表拆分成多个表,这解决了表的宽度问题.
2. 垂直拆分的原则:
1. 把不常用的字段表单独存放到一个表中。
2. 把大字段独立存放到一个表中。
3. 把经常一起使用的字段放到一起。
以如下三张表为例:
ap_article
CREATE TABLE `ap_article` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标题',
`author_id` int(11) unsigned DEFAULT NULL COMMENT '文章作者的ID',
`author_name` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '作者昵称',
`channel_id` int(10) unsigned DEFAULT NULL COMMENT '文章所属频道ID',
`channel_name` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '频道名称',
`layout` tinyint(1) unsigned DEFAULT NULL COMMENT '文章布局\r\n 0 无图文章\r\n 1 单图文章\r\n 2 多图文章',
`flag` tinyint(3) unsigned DEFAULT NULL COMMENT '文章标记\r\n 0 普通文章\r\n 1 热点文章\r\n 2 置顶文章\r\n 3 精品文章\r\n 4 大V 文章',
`images` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文章图片\r\n 多张逗号分隔',
`labels` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文章标签最多3个 逗号分隔',
`likes` int(5) unsigned DEFAULT NULL COMMENT '点赞数量',
`collection` int(5) unsigned DEFAULT NULL COMMENT '收藏数量',
`comment` int(5) unsigned DEFAULT NULL COMMENT '评论数量',
`views` int(5) unsigned DEFAULT NULL COMMENT '阅读数量',
`province_id` int(11) unsigned DEFAULT NULL COMMENT '省市',
`city_id` int(11) unsigned DEFAULT NULL COMMENT '市区',
`county_id` int(11) unsigned DEFAULT NULL COMMENT '区县',
`created_time` datetime DEFAULT NULL COMMENT '创建时间',
`publish_time` datetime DEFAULT NULL COMMENT '发布时间',
`sync_status` tinyint(1) DEFAULT '0' COMMENT '同步状态',
`origin` tinyint(1) unsigned DEFAULT '0' COMMENT '来源',
`static_url` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1383828014629179394 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='文章信息表,存储已发布的文章';
ap_article_config
CREATE TABLE `ap_article_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`article_id` bigint(20) unsigned DEFAULT NULL COMMENT '文章ID',
`is_comment` tinyint(1) unsigned DEFAULT NULL COMMENT '是否可评论',
`is_forward` tinyint(1) unsigned DEFAULT NULL COMMENT '是否转发',
`is_down` tinyint(1) unsigned DEFAULT NULL COMMENT '是否下架',
`is_delete` tinyint(1) unsigned DEFAULT NULL COMMENT '是否已删除',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_article_id` (`article_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1383828014645956610 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='APP已发布文章配置表';
ap_article_content
CREATE TABLE `ap_article_content` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`article_id` bigint(20) unsigned DEFAULT NULL COMMENT '文章ID',
`content` longtext COLLATE utf8mb4_unicode_ci COMMENT '文章内容',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_article_id` (`article_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1383828014650150915 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='APP已发布文章内容表';
- 第一张表 ap_article,都是文章的一些基本信息
- 第二张表 ap_article_config 表的字段特征都是一些经常需要查询的字段信息(高频查询字段)
- 第三张表 ap_article_content 大字段信息,当文章内容比较大时,查询的话性能一般不会太好
垂直拆分的目的
将文章的基本字段,经常查询的字段,大文本字段做了垂直拆分,进而提高数据库的查询效率
垂直拆分解决了表与表之间的IO竞争
优点:
1、拆分后业务清晰,拆分规则明确。
2、系统之间整合或扩展容易。
3、数据维护简单。
缺点:
1、部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。
2、受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。
3、事务处理复杂。
水平拆分
水平拆分的定义
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放
如果单表的数据量达到上亿条,那么这时候我们尽管加了完美的索引,查询效率低,写入的效率也相应的降低。
优点:
1. 不存在单库大数据,高并发的性能瓶颈。
2. 对应用透明,应用端改造较少。
3. 按照合理拆分规则拆分,join操作基本避免跨库。
4. 提高了系统的稳定性跟负载能力。
缺点:
1. 拆分规则难以抽象。
2. 分片事务一致性难以解决。
3. 数据多次扩展难度跟维护量极大。
4. 跨库join性能较差。
水平拆分的方案
范围、枚举、时间、取模、哈希、指定
通常情况下,我们使用取模的方式进行拆分,例如一张400w数据的表,为提高查询效率,我们将其分成四张表(一模一样)
然后通过ID取模的方式将数据分散到四张表中, ID%4 + 1 = [1, 2, 3, 4]
因此查询更新删除时,我们都可以通过取模的方式获取
对于查询:
我们还需要一张临时表来存储原始表的自增id。 (唯一用处就是提供自增ID)
得到ID以后,再通过取模进行插入数据