SQL巩固以及数据库、表结构优化

SQL巩固&数据库、表结构优化

前言

对于初级程序开发工程师而言,SQL是很多人的弱项,为此我给大家来做一下总结,希望能够帮到你们。

课程说明

1、介绍项目实战开发过程中常用的MySQL函数及常用语法,并且分析三种联合查询原理及如何使用、什么时候使用;

2、针对数据库层面的优化方案做介绍说明;

SQL巩固

初始化

说明:这里用大家熟知的电商业务来讲解,进一步巩固学习SQL

表结构创建

订单表

CREATE TABLE `tb_order` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单id',
   `user_id` int(11) NOT NULL COMMENT '用户id',
   `price` int(11) NOT NULL COMMENT '订单金额',
   `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
   `create_time` datetime NOT NULL COMMENT '创建时间',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '订单状态',
   `update_time` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`id`),
   KEY `IDX_USER_ID` (`user_id`),
   KEY `IDX_PAY_TIME` (`pay_time`),
   KEY `IDX_CREATE_TIME` (`create_time`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='订单表'

商品表

CREATE TABLE `tb_goods` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id',
   `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
   `price` int(11) NOT NULL DEFAULT '0' COMMENT '单价',
   `stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存',
   `status` smallint(6) NOT NULL DEFAULT '0' COMMENT '状态',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='商品表';
  -- goods_2表
 CREATE TABLE `tb_goods_2` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `name` varchar(32) DEFAULT NULL,
   `code` varchar(16) DEFAULT NULL COMMENT '商品编码',
   `business_id` int(11) DEFAULT NULL COMMENT '商家id',
   `price` int(11) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `IDX_B_C` (`business_id`,`code`),
   KEY `IDX_CODE` (`code`)
 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC

由于一个订单可能包含多种商品,故存在

订单商品关系表

CREATE TABLE `tb_order_goods` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '关联数据id',
   `order_id` int(11) NOT NULL COMMENT '订单id',
   `goods_id` int(11) NOT NULL COMMENT '商品id',
   `goods_num` int(11) NOT NULL COMMENT '商品数量',
   `goods_price` int(11) NOT NULL COMMENT '商品单价',
   `sum_price` int(11) NOT NULL COMMENT '小计金额',
   PRIMARY KEY (`id`),
   KEY `IDX_ORDER_ID` (`order_id`),
   KEY `IDX_GOODS_ID` (`goods_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='商品订单关系表'

用户表

CREATE TABLE `tb_user` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
   `name` varchar(32) DEFAULT NULL COMMENT '姓名',
   `phone` varchar(15) NOT NULL DEFAULT '' COMMENT '电话',
   `sex` varchar(1) DEFAULT NULL COMMENT '性别',
   `password` varchar(64) DEFAULT NULL COMMENT '密码',
   `user_name` varchar(18) NOT NULL COMMENT '用户名',
   `status` tinyint(3) DEFAULT NULL COMMENT '状态',
   PRIMARY KEY (`id`),
   KEY `IDX_PHONE` (`phone`),
   KEY `IDX_USER_NAME` (`user_name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='用户表';
 -- user_2表
 CREATE TABLE `tb_user_2` (
   `id` int(11) NOT NULL,
   `name` varchar(32) DEFAULT NULL,
   `password` varchar(32) DEFAULT NULL,
   `sex` varchar(1) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `IDX_NAME` (`name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='用户表2'

有的同学想要知道,针对已存在的表结构,如何添加索引呢?简单演示如下

给tb_user表name字段添加普通索引

-- IDX_NAME 为索引名,可自行定义
ALTER TABLE `tb_user` ADD INDEX `IDX_NAME` (`name`);

添加测试数据

INSERT  INTO `tb_goods`(`id`,`name`,`price`,`stock`,`status`) VALUES (1,'华为P30',600000,20,1),(2,'美特斯邦威男士夹克衫',29900,100,1);
INSERT  INTO `tb_order`(`id`,`user_id`,`price`,`pay_time`,`create_time`,`status`,`update_time`) VALUES (1,1,629900,'2020-02-01 00:00:00','2020-02-01 00:00:00',1,'2020-02-01 00:00:00'),(2,1,1200000,NULL,'2020-02-02 00:00:00',0,'2020-02-02 00:00:00'),(3,2,600000,'2020-03-01 00:00:00','2020-03-01 00:00:00',1,'2020-03-01 00:00:00');
INSERT  INTO `tb_order_goods`(`id`,`order_id`,`goods_id`,`goods_num`,`goods_price`,`sum_price`) VALUES (1,1,1,1,600000,600000),(2,1,2,1,29900,29900),(3,2,1,2,600000,1200000),(4,3,1,1,600000,600000);
INSERT  INTO `tb_user`(`id`,`name`,`phone`,`sex`,`password`,`user_name`,`status`) VALUES (1,'高M','18810531708','男','123456','gao_yue',1),(2,'明哥','18810532526','男','123654','tang_',1),(3,'培哥','15544455665','男','545466','pei_',1);

常见操作

COUNT累计

COUNT(值),这个值如果不是null则计1,值为null则计0

  • 所以select count(1) from dual;select count(10000) from dual其结果都为1

  • select count(null) from dual结果则为0

例如tb_user表中有三条数据,其中有一条数据的name字段为空,那么存在

  • select count(name) from tb_user结果则为2而非3,如果想要统计表中数据条数则用count(*)或count(id)
  • 另外值得一说的是,select 1000 from tb_user表,其结果为3行1000,所以存在如下
  • select count(1000) from tb_user结果为3

count结合distinct使用可统计某个字段出现(除空值之外的)不同值的次数

比如查询订单表有多少笔金额相同的订单

select count(distinct(price)) from tb_order;

SUM累加

SUM(值),会把这个值的数值进行一个累加,sum(null)则为null

所以select sum(0) from dual结果为0,select sum(1000) from dual结果为1000

select sum(null) from dual结果为null

故针对sum的字段如果可能出现null的话,需要提前做判断转换IFNULL(字段,代替值),避免出现统计错误

比如统计订单表订单销售总额(不区分订单状态)

select sum(IFNULL(price,0)) from tb_order;

DISTINCT去重

比如我们要查询所有下过单的用户id集合,这里结果集中针对相同id要做去重处理

SELECT DISTINCT user_id FROM tb_order;

GROUP BY、HAVING、ORDER BY

按某个字段分组——GROUP BY

分组之后,对于分组统计的结果再做条件筛选——HAVING

对于结果集按照某个字段进行排序——ORDER BY

在查询结果集之上再做查询

select 

s1.a, s1.b, s1.c, s2.e, s2.f
from

(select a, b, c from t1 where **) s1

*** join 

(select a, e, f from t2 where **) s2

on s1.a = s2.a

...

结果集行号、rownum

-- oracle数据库可以在查询语句中使用rownum关键字来获取结果集的行号
select rownum,id,name from student;
SELECT @rowNum:=@rowNum + 1 AS '行号',a.* FROM tableName a,(SELECT @rowNum:=0) b
-- 按订单金额排名 1、2、3...
SELECT 
@rowNum:=@rowNum + 1 AS '行号', -- 名次
a.* FROM tb_order a,
(SELECT @rowNum:=0) b
ORDER BY price DESC;

在这里插入图片描述

CASE WHEN THEN ELSE END

-- 统计 订单表中 未支付订单数、已支付订单数
SELECT 
COUNT(CASE WHEN `status` = 0 THEN 1 ELSE NULL END) AS '未支付订单数',
COUNT(CASE WHEN `status` = 1 THEN 1 ELSE NULL END) AS '已支付订单数'
FROM tb_order;

在这里插入图片描述

-- 查询订单表 各个支付状态 对应的 订单数
SELECT 
(CASE WHEN `status` = 0 THEN '未支付' WHEN `status` = 1 THEN '已支付' END) AS '支付状态',
COUNT(id) AS '订单数'
FROM
tb_order 
GROUP BY `status`;

在这里插入图片描述

不用max、min如何找最大、最小

order by 
-- 结合 
limit 1
-- 一起使用
--查询订单表 金额最大订单 对应的用户信息
SELECT 
s2.name,
s2.id
FROM
(SELECT user_id FROM tb_order ORDER BY price DESC LIMIT 1) s1
INNER JOIN 
tb_user s2
ON s2.id = s1.user_id

日期常见操作

now()

查询当前日期时间

current_date、current_time

查询当前日期、当前时间

SELECT NOW(),CURRENT_DATE,CURRENT_TIME

在这里插入图片描述

date_format()

日期格式化操作,常用

-- 按日统计订单数,数据量过大会导致慢查询,就算create_time是建立了索引的,建议优化
-- 优化方向
-- 1、缩小范围
-- 2、冗余年月日字段
-- 3、数据同步,数据仓库,报表中台。不要从实时业务生产数据库查询统计相关数据
SELECT 
DATE_FORMAT(create_time,'%Y-%m-%d') AS '日期',
COUNT(id) AS '下单量',
SUM(IFNULL(price,0)) AS '下单金额',
MAX(price) AS '最大订单金额'
FROM tb_order
GROUP BY DATE_FORMAT(create_time,'%Y-%m-%d');

在这里插入图片描述

SELECT DATE_FORMAT(NOW(),'%Y.%m.%d %T');

在这里插入图片描述

UNIX_TIMESTAMP
-- 获取 dateTime 字段时间戳
SELECT UNIX_TIMESTAMP(NOW());

在这里插入图片描述

DATE_SUB、DATE_ADD

查询某个日期之前、之后

# 日期 操作的 函数 date_add、date_sub
-- 三分钟之后
SELECT DATE_ADD(NOW(),INTERVAL 3 MINUTE);
-- 30个月之前
SELECT DATE_SUB(NOW(),INTERVAL 30 MONTH);
-- 3天之前
SELECT DATE_SUB(NOW(),INTERVAL 3 DAY);
-- 指定某个日期查询其之前或之后
SELECT DATE_SUB('2019-08-09 12:08:08',INTERVAL 3 DAY);

字符串常见操作

CONCAT

拼接字符串

-- 用于拼接字符串的参数个数不限定
SELECT CONCAT('a','bcd','efg') -- abcdefg
SELECT CONCAT(id,`name`) FROM tb_user;
SUBSTR

截取字符串

SELECT SUBSTR('12345',1,3); -- 123
SELECT SUBSTR('12345',3); -- 345
LEFT、RIGHT

从右边、左边开始 截取多少位字符串

SELECT LEFT('2019-08-09 12:08:08',10);
SELECT LEFT(create_time,10) FROM tb_order; -- 年-月-日
SELECT RIGHT(create_time,8) FROM tb_order; -- 时:分:秒
-- 可以达到 跟 DATE_FORMAT相同的目的
SELECT DATE_FORMAT('2019-08-09 12:08:08','%Y-%d-%m');

IF、男女性别互换

-- 用sql把用户表的性别为男的变成女的,女的变成男的
-- 可以用case when
UPDATE
tb_user_2
SET
sex = (CASE WHEN sex = '女' THEN '男' WHEN sex = '男' THEN '女' END);
-- 推荐使用IF
-- 用IF,当表达式条件成立,则用第一个值,否则用第二个值。类似 Java中的 三元运算
UPDATE
tb_user_2
SET
sex = IF(sex='女','男','女'); -- 这里的 '男' 为第一个值,'女' 为第二个值

联合更新

-- 把订单表中订单金额 (只要用户有任何一个订单金额超过1000即可) 超过1000的用户的状态更新为999
-- 首先需要确认的是,使用内连接。
-- 中间结果集
SELECT t1.*,t2.* FROM
tb_user t1
INNER JOIN # 内联接
tb_order t2
ON t1.id = t2.user_id;
-- 具体更新操作
UPDATE
tb_user t1
INNER JOIN
tb_order t2
ON t1.id = t2.user_id
SET 
t1.status = 999
WHERE
t2.price > 1000;
-- 优化版本,减少更新判断的次数
-- 中间结果集
SELECT t1.*,t2.* FROM
tb_user t1
INNER JOIN # 内联接
(SELECT user_id,MAX(price) FROM tb_order GROUP BY user_id HAVING MAX(price)>1000) t2
ON t1.id = t2.user_id;
-- 具体更新操作
UPDATE
tb_user t1
INNER JOIN
(SELECT user_id,MAX(price) FROM tb_order GROUP BY user_id HAVING MAX(price)>1000) t2
ON t1.id = t2.user_id
SET 
t1.status = 999;
-- 搞个额外的活动,找出在我们平台下过单的用户,当订单总金额超过100W,把用户变成超级VIP -- 100
-- 需要用到分组聚合
-- 中间结果集
SELECT t1.*,t2.* FROM
tb_user t1
INNER JOIN -- 内联接
(SELECT user_id,SUM(IFNULL(price,0)) FROM tb_order GROUP BY user_id HAVING SUM(price)>1000000) t2
ON t1.id = t2.user_id;
-- 具体更新操作
UPDATE
tb_user t1
INNER JOIN -- 内联接
(SELECT user_id,SUM(IFNULL(price,0)) FROM tb_order GROUP BY user_id HAVING SUM(price)>1000000) t2
ON t1.id = t2.user_id
SET 
t1.status = 100;

查询结果集导入表

-- 将查询的 结果集 直接导入某个表
INSERT INTO tb_user_2
SELECT 
tb_user.id,
tb_user.name,
tb_user.password,
tb_user.sex AS 'sex'
FROM tb_user
WHERE
sex = '女';

UNION、UNION ALL

把多个结果集进行整合,整合成一个结果集,要求每个结果集字段一致

union会将全字段完全一样的数据去重,union all则不会去除重复数据

-- UNION 、UNION ALL
-- UNION ALL
(SELECT 
tb_user.id,
tb_user.name,
tb_user.password,
tb_user.sex AS 'sex'
FROM tb_user
WHERE
sex = '女')
UNION ALL -- 不会去重
(SELECT * FROM tb_user_2)
-- UNION
(SELECT 
tb_user.id,
tb_user.name,
tb_user.password,
tb_user.sex AS 'sex'
FROM tb_user
WHERE
sex = '女')
UNION  -- 会去重
(SELECT * FROM tb_user_2)

联合查询

LEFT JOIN

SQL巩固以及数据库、表结构优化_第1张图片
当某个学生的成绩录入了两次(1对多)时(而如果是多对多,则会出现笛卡尔积)
SQL巩固以及数据库、表结构优化_第2张图片

RIGHT JOIN

SQL巩固以及数据库、表结构优化_第3张图片
实则a left join b 跟 b right join a 结果集数据是一致的,不同的是字段的位置而已
SQL巩固以及数据库、表结构优化_第4张图片

INNER JOIN、逗号连接

这两种查询方式结果是一致的
SQL巩固以及数据库、表结构优化_第5张图片

FULL JOIN

MySQL貌似不支持
SQL巩固以及数据库、表结构优化_第6张图片

这么多join方式如何选择

以学生表、成绩表为例

  1. 查询没有学生成绩的学生姓名;(查看哪一些学生没有交卷)—— student left join score

    需要查询学生姓名,那么学生信息不能为空;

    需要查询的学生是没有成绩的,那么成绩需要为空(null);

  2. 查询成绩最好的学生姓名;—— student inner join score

    成绩最好:说明这个学生肯定有成绩,这个学生id必须在成绩表中存在;

    姓名:说明这个学生在学生表里面肯定也存在;

    那么用inner join

你应该知道的

联合索引按左匹配

-- 联合索引 按左 匹配原则
--比如 某个联合索引 由 a,b,c 构成

-- 如下查询无法命中索引
SELECT * FROM tb_ WHERE b = **;
SELECT * FROM tb_ WHERE c = **;
SELECT * FROM tb_ WHERE c = ** AND b = ***;
SELECT * FROM tb_ WHERE c = ** AND a = ***;

--要想 c 这部分 索引能够生效使用,必须要求 查询的 条件中 有 b 字段 这个条件
--要想 b 这部分 索引能够生效使用,必须要求 查询的 条件中 有 a 字段 这个条件
SELECT * FROM tb_ WHERE b = ** AND a = ***; -- 查询能够命中联合索引 的 a、b 部分
SELECT * FROM tb_ WHERE c = ** AND b = *** AND a = ****; -- 查询能够命中联合索引 的 a、b、c 部分
-- 联合索引 最左 匹配的原则

-- IDX_B_C business_id, code ——从业务转化而来
-- 业务中,有大量的关于 code的查询,都是 一定会携带 business_id
-- 更形象的例子,我们是一个B 平台,有很多小B入驻
-- 每个小B在我们平台给他们提供的后台管理系统中,他们 只能 访问 自己的商品数据,
-- 必定在查寻数据的时候会携带商家id,我们后台肯定知道当前登陆的用户是谁,也就知道了是哪个商家

数据库、表结构优化

优化的必要性

  1. 减轻关系型数据库访问压力,提升程序负载能力;(程序的瓶颈一般是体现在数据库访问的瓶颈之上)

  2. 加快响应速度,提升用户体验;

  3. 慢查询引起的生产事故;因为慢查询的存在(也有可能是数据库、表结构设计不合理导致的)导致一些非常简单的sql语句都没法执行。从而引起生产问题。

  4. 表结构重构、数据迁移是巨大的工程;拓展性不好

    想到业务后期有可能发展成什么样子,提前将这种关系考虑到,然后再进行表结构设计

    防止后期拓展字段需要变动数据库表结构,可以如此设计:冗余一个 expand varchar 510 ----- json 对象 字符串

  5. 关系型数据库针对某些数据的存储不是那么合适;

数据库表结构合理设计

数据库设计三范式

  1. 每一列是不可再分的属性值,同一列不能包含多个值,关系型数据库的特点之一;

    地址:省、市、区、具体地址

  2. 数据库表中每个实例或行必须可以被唯一地区分;

    需要有唯一能区分行数据的字段(主键)

  3. 一个数据表中不再包含已在其它表中包含的非主关键字信息(看情况);

    订单数据,包含用户id,不再存储用户其它数据(看情况),(分布式系统中,比如下单时的用户手机号…)

设计符合业务的表结构

  1. 比如业务流程中,有明显的区分使用用户基础数据跟用户详情数据可以对应的建立用户基础表、用户详情表;
  2. 多对多的关系设计中,使用中间关联表,如品牌表、分类表、品牌分类关联表;

主从同步、读写分离

一主一从,一主多从的架构方式

利用主从数据库来实现读写分离,从而分担主数据库的压力。在多个服务器上部署mysql,将其中一台认为主数据库,而其他为从数据库,实现主从同步。其中主数据库负责主动写的操作,而从数据库则只负责主动读的操作(slave从数据库仍然会被动的进行写操作,为了保持数据一致性),这样就可以很大程度上的避免数据丢失的问题,同时也可减少数据库的连接,减轻主数据库的负载。

https://blog.csdn.net/qq_15092079/article/details/81672920

主库用来写数据,可读可写

从库只允许读数据,不允许写数据

减轻单个MySQL的压力,提升并发访问能力,提升数据库性能
SQL巩固以及数据库、表结构优化_第7张图片

存在的问题

主从数据库之间数据同步的问题
SQL巩固以及数据库、表结构优化_第8张图片

同步复制方案效率较低,一般采用默认同步方式:异步复制

在并发访问较大的情况下,导致数据库服务压力飙升,可能导致主从数据同步存在一定的延迟,需要从业务的角度做适配。或者采取指定主库查询的方式来避免这种问题。但是我们作为技术开发人员,需要知道这个问题是肯定存在的。

缓存

缓存是将数据从数据库(数据在磁盘上)复制到内存中,用户访问数据时,直接从内存中获取数据。这样就可以提升数据访问的效率,提升系统的并发访问量,提升用户体验,提升整个系统的吞吐量。是互联网产品技术实现中经常采用的方案。

MySQL缓存

详见:https://www.cnblogs.com/yueyun00/p/10898677.html

如SQL语句:select * from tb_user where id = 10010;在MySQL服务执行完以后,MySQL会从磁盘查询到具体的数据返回客户端,并且将【sql:查询的结果集】进行映射缓存,保存到MySQL服务的内存中;

在tb_user表结构、数据没有发生变动(delete、insert、update…)时,执行相同的SQL语句,会根据SQL直接从内存中获取结果返回,不会再去查找读取磁盘,加快访问速度。当表数据发送变动,会将跟这个表相关的缓存结果数据进行清除。

服务本地缓存

例如:Java服务本地缓存,缓存在Java进程开辟的内存空间中

优势:速度更快,架构方式更加简单;

劣势:一致性问题,多进程间缓存无法实现共享,缓存的数据量不易拓展,对服务本身的入侵性太强,缓存的可用性得依靠服务自身;

分布式缓存

Redis缓存

分布式部署,满足大量数据需要缓存的业务场景,实现分布式服务场景下的缓存共享;

通过单独的缓存服务进行部署维护,缓存的访问需要依靠网络通信;

分库分表

解决单库数据存储压力过大的问题

按业务垂直拆分——分库

把同一个库中的多个表,按照业务进行垂直划分,拆分到多个数据库中,每个库会单独处理具体的业务数据;

按数据水平拆分——分表

一张表数据量太大,破千万甚至过亿,我们不得不将一张表中的数据拆分到多张表中;

具体数据需要存储到哪张表,或者查询时需要从哪张表进行搜索,都需要经过算法操作,一般业界会采用成熟的中间件,来访问我们的数据库,我们作为客户端,只需要使用(访问)中间件即可;(mycat、shardingJDBC…)

NoSQL

非关系型的数据库

存在的意义,填补关系型数据库的不足,为关系型数据库存储做补充;根据K去找对应的V,当然需要经过一个算法分析,当前这个kv数据存储在哪个节点上面;

K:V存储,便于线性拓展(以Redis理解),多用于海量的数据存储(几十亿、百亿数据),日志数据,用户报告数据、用户消费情况、足迹;

典型的代表:MongoDB、Redis、HBASE、TableStore

NewSQL

这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库支持ACID和SQL等特性;

NewSQL是指这样一类新式的关系型数据库管理系统,针对OLTP(读-写)工作负载,追求提供和NoSQL系统相同的扩展性能,且仍然保持ACID和SQL等特性;

NewSQL系统虽然在的内部结构变化很大,但是它们有两个显着的共同特点:(1)它们都支持关系数据模型,(2) 它们都使用SQL作为其主要的接口。

数据归档

定期清理业务不需要使用的数据(历史数据),从实时业务数据库表中移除,保存到历史表,减轻实时业务生成数据表的压力;

比如:十年前的 订单数据;从具体业务层面来做数据归档操作;

数据中台、数仓

最高层面的一种数据库的优化手段。只是针对的对数据有需求的 业务 做的 优化手段;

我们的所有关于数据分析类的查询,都不再查询实时业务生产数据库,或者是说将搜索业务从实时业务生成数据库进行剥离,从源头上解决数据需求的问题!

用空间来换时间的一种操作方式。

数据如何同步到数据仓? 多采用 异步收集,canal、maxwell、日志、定时任务查询(凌晨)

存在的问题:数据一致性问题,存储的问题,可采用NoSQL等数据库做适应性存储;一致性的问题,需要从业务角度做适配;

非结构化的数据(分散的数据) ----> 结构化的数据(具体业务能够直接使用的数据)

存储引擎优化

InnoDB

事务型数据库的首选引擎

实时业务生产数据库表存储引擎

MyISAM

拥有较高的插入、查询速度,但不支持事物

非实时业务生产,如 数据仓库 等 数据应用数据库环境

Memory

临时存放数据,数据量不大,并且不需要较高的数据安全性,效率高;

MySQL中使用该引擎作为临时表,存放查询的中间结果。

你可能感兴趣的:(数据库)