数据库介绍

目录

Mysql

特点优势

数据库/SQL优化

explain

索引

事务特性ACID、隔离级别、MVCC

日志

分库分表

并发、 并行

Redis

Redis持久化

分布式锁

 redis实现数据一致性

缓存雪崩、击穿、穿透

MongoDB 

ClickHouse

1、概述

2、产生背景

3、发展历史

4、ClickHouse应用场景

5、启动

6、命令

Mysql

特点优势

mysql:轻量级(发行版21M,安装完成也仅51M)
             简单易用性能高(运行速度:开发者声称是目前最快的数据库)
             自行安装免费
             支持windows/Linux
             安全性(完全网络化的,其数据库可在因特网上的任何地方访问;还能进行访问控制,控制哪些人不能看到您的数据)
缺点:不支持热备份,最大的缺点是其安全系统复杂不标准
           由Unix或Linux第三方安装收费,自行安装免费
oracle:安全性较高(获得最高认证级别的ISO标准认证)
             对硬件要求较高、操作较复杂、价格较高
SqlServer:不安全(没有获得任何安全证书)

默认端口:oracle-1521、sqlserver-1433、mysql-3306、Tomcat-8080 

utf8在my.ini设置,设置的是mysql的语言编码;创建表(charset属性)时不设置,会出现乱码问题,二者作用域不一样;

数据库/SQL优化

1、范式:防止数据冗余,七大范式(1NF ->6NF、BCNF鲍依斯-科得范式)
2、索引:正确使用索引、explain分析、建联合索引实现覆盖索引减少回表

1)*Tree索引:Create index index_name on table_name (column[column…])
2)反向索引:Create index index_name on table_name (column[column…]) reverse
3)降序索引:Create index index_name on table_name (column DESC[column…])
4)位图索引:Create BITMAP index index_name on table_name (column[column…])
5)函数索引:Create index index_name on table_name (function(column))
另有普通索引、UNIQUE索引:create unique index index_name on table_name (column_list)
alter table方式创建:有普通索引、UNIQUE索引、PRIMARY KEY索引,一次可创建多个,只对表扫描一次,效率更高;

index_name可选,不写mysql会根据第一个索引列赋一个名称
alter table table_name add PRIMARY KEY ( column ), add UNIQUE ( column ),
add INDEX index_name ( column ),  add FULLTEXT( column )  -- 还有全文索引
add INDEX index_name ( column1, column2…)  -- 联合索引

3、distinct、用exists不用 in 、or用union all

查询已绑定设备的店铺:

select * from shop_info as s where

          exists (select shop_id from shop_binding_device_record where shop_id = s.id);

select * from shop_info as s where

          id in (select shop_id from shop_binding_device_record where shop_id = s.id);

原理:小表驱动大表(数据量少的表是小表),例如,小表140条数据,即只需要通过140次的连接就可以;

1)left join时,左表是驱动表;right join时,右表是驱动表;
      使用join,mysql会选择数据量小的表作为驱动表

2)explain语句分析出来的第一行的表即是驱动表

select id from t where num=1 union all select id from t where num=2

4、SQL语句尽量简单,不嵌套太多层;连表查询以小表驱动大表,通过冗余字段避免连表最好
5、用临时表缓存中间结果,避免多次扫描主表,减少阻塞,提高并发性能
6、考虑查询强制使用索引
select * from t force index(PRI) (强制使用主键)
select * from t force index(ind) (强制使用索引ind)
select * from t force index(PRI,ind) (强制使用索引"PRI和ind")
7、具体字段列表代替 select *
8、用数字型类型,只含数值信息字段不设计为字符,会降低查询和连接性能,且增加存储开销
9、索引不是越多越好,提高查询效率,但也降低insert及update的效率

explain

id:select的序列号,有几个select就有几个id,id值越大,优先级越高,越先执行
select_type:显示本行是简单或复杂select,如果查询有任何复杂的子查询,则最外层标记为PRIMARY(DERIVED、UNION、UNION RESUlT)
table:查询的表名或表别名
type:表的访问类型,效率高低:const、eq_ref、ref、range、index、all
possible_keys:能使用哪个索引在表中找到行
key:实际使用的索引,如果没有选择索引,值是NULL
key_len:实际使用的索引长度(单位:字节),该字段显示为索引字段的最大可能长度,非实际使用长度
ref:用于索引查找的值的来源,如果值为常量,则 ref 为 const
rows:查询需要扫描的行数(在表或索引树中)
filtered:查询条件所过滤的行记录数占比
Extra:额外信息:Using index、Using where等

索引

show index from  shop_info  -- 查看一个表的索引

失效情况
1)or,但将or条件中的每个列都加上索引不失效
2)数学运算,函数,like,使用不等于(<>)索引效果一般
3)mysql估计全表扫描 比 使用索引快,不使用索引,如数据量极少的表
4)数据唯一性差, 比如性别只有两个值。意味着索引二叉树级别少,这样查找无异于全表扫描
5)频繁更新的字段不使用索引,频繁变化导致索引也频繁变化,增大数据库工作量

数据结构:B+树,多路平衡查找树,应数据库需要出现的一种B树(也叫B-树)变形树,高度更矮,通常默认深度是3,所以就算几百万的数据也只需要3次IO,可以有多个子节点,一个节点可以存储多个值;
与B树不同之处在于
1)所有数据存储在叶子节点,非叶子节点存储一些关键字及指向下个节点的索引,B树是所有节点都存储数据,导致存储的数据少,需要增加高度,性能也就更低

所以节点相对较小,基本一次性加载到内存,查询时先查内存,查到数据后,才去访问磁盘(数据存储在磁盘里),就是常说的回表;

若查询的字段设置了索引,直接从b+树上返回数据;

回表就是取从b+树上拿不到的数据,需通过聚簇索引去访问磁盘拿;


聚簇索引:找到了索引就找到了需要的数据,就是聚簇索引,主键是聚簇索引
非聚簇索引:索引和数据的存储分离,找到索引后,要根据索引上的值再次回表查询,也叫做辅助索引

2)所有叶子结点之间有指针相连,且按顺序排列,范围查询的时候效率很高
3)平衡性,子节点数量超过阈值,另起父节点存储

索引下推、覆盖索引
select name,age from t_user where name like ‘l%’ ;
没建索引:是常规写法(回表查询),在数据库中的执行过程是:
第一步:全表扫描数据,找出以“l”开头的主键id.
第二步:将所有查询出来的数据每一个都回表,根据id来查询出想要的数据。

优化写法

覆盖索引:对name和age建立联合索引后,当我们查询name和age二个字段时,直接会从索引中查出来name和age,而不需要回表查询,这种方式就是覆盖索引;


索引下推:是 MySQL 5.6 及以上版本推出,默认开启,用于对查询进行优化,把本应该在 server 层进行筛选的条件,下推到存储引擎层来进行筛选判断,这样能有效减少回表;
例子:select * from t_user where name like ‘L%’ and age = 17;
使用索引下推的执行过程:
1:利用索引找出name带’L’的数据行:LiLei、Lili、Lisa、Lucy 这四条索引数据
2:根据age=17 这个条件,对四条索引数据进行判断筛选,最终只留下 Lucy 的数据信息
(注意:这一步不进行回表,先进行判断筛选)
3:将符合条件的索引对应的 id 进行回表扫描,最终将找到的行数据返回给 server 层

联合索引最左匹配原则:如果是 where a > xxx and b = xxx ,即建索引时可以对 (b, a) 建立索引,就是将选择性高的列放在索引的最前列,遇到范围查询(>、<、between、like等)的列索引失效。

事务特性ACID、隔离级别、MVCC

原子性:一个事务要么完全执行,要么根本不执行
一致性:一个事务在它完成后不能留下系统的不一致性
隔离性:所有的事务不许允许在执行的时候受其他事务的干涉
持久性:在事务期间,所有提交的变更数据是永久变更的
事务支持由存储引擎决定:
1)MyISAM:不支持事务,用于只读程序提高性能
2)Berkeley DB:支持事务
3)InnoDB:支持ACID事务、行级锁、并发

开启事务

1)begin、start transcation

START TRANSACTION;
事务代码
commit / rollback;

2)set autocommit = 0

autocommit 默认 1,自动提交事务,autommit是session级别,就是当前连接更改了autocommit,对其他连接没有影响;设置autocommit后,本次连接的所有 sql 都是事务的形式,需要手动commit

4个隔离级别
1)READ UNCOMMITTED:dirty read,一个事务可读取还没commit的数据;
2)READ COMMITTED:一个事务只读取已经commit的数据,产生不可重复读,即两次读取的数据可能不一致;
3)REPEATABLE READ:其他事务对数据库的修改在本事务中不可见,解决不可重复读,产生幻读,如新添加的数据本事务查询不到,默认的隔离级别
4)SERIALIZABLE:最高隔离级别,只允许事务串行执行,读写会锁住整个表;
写法:set transaction isolation LEVEL {READ UNCOMMITTED | ... | SERIALIZABLE}
采用MVCC(多版本并发控制)解决事务的安全问题,可解决脏读、不可重复读等事务隔离问题,不能解决更新丢失问题;

解决幻读分情况:

快照读能解决,当前读使用next-key lock(一个行锁record lock+范围锁gap lock)解决
mysql两种读:

1)快照读–select查询
2)当前读–会对数据修改的操作(update、insert、delete),和select 加了lock in share mode,for update的都是当前读

1)MVCC优势:读不加锁,乐观锁的一种体现,即提高了数据库并发性能;
2)只能在READ COMMITTED、REPEATABLE READ两个隔离级别下工作,
因为READ UNCOMMITTED是读取最新的数据行,而不是符合当前事务版本的数据行,SERIALIZABLE则对所有读取的行都加锁
底层实现:基于版本链和基于快照
1)基于版本链:在数据库中为每个数据行保存多个版本,每个版本有一个唯一的时间戳。当事务读取数据,它只能看到在该事务开始之前已经提交的版本;当事务修改数据时,会创建一个新的版本,并且只有该事务可以看到这个新版本
2)基于快照:在数据库中为每个事务创建一个快照,该快照包含了该事务开始之前已经提交的数据版本。当事务读取数据时,它只能看到自己创建的快照中的数据;

按锁粒度:行级锁、页级锁、表级锁

行级锁:引擎INNODB,单独的一行记录加锁,有两种模式--共享锁、排他锁;

页级锁:引擎BDB ,大小4kb;

表级锁:引擎MyISAM,理解为锁住整个表,可以同时读,写不行

按锁级别:共享锁、排他锁、意向锁

SELECT … LOCK IN SHARE MODE,锁住的这些数据只能读不能修改;
加FOR UPDATE,对查询的每行都加排他锁,InnoDB引擎默认的update,delete,insert都会自动给涉及到的数据加上排他锁,获取排他锁的事务可以对数据就行读取和修改

乐观锁、悲观锁(mysql两种设计结构)
1)乐观锁:读取数据时不锁,进行业务操作后再去获取锁,表字段加version实现
update goods_sale set count = #{count}, version = version + 1
where id = #{id} and version = #{version}
执行这个sql 时候对数据上行锁,version 加 1 的操作属于原子操作
2)悲观锁:读取数据时先获取锁,再进行业务操作,加for update就属于是悲观锁结构。

日志

日志分析工具mysqldumpslow 

1、重做日志(redo log):记录事务执行后的状态,确保了事务持久性,对应的物理文件位于数据库的data目录下的ib_logfile1&ib_logfile2
2、回滚日志(undo log):保存了事务发生之前的数据,确保了事务原子性,可用于回滚
3、二进制日志(bin log):用于主从复制,主库将sql记录写入bin log,从库向主库发请求读取bin log,从库将主库发送的日志先写入到中继日志,再开线程读取中继日志将数据写入数据库中(主从复制模式缓解单服务器的压力,写操作给主服务器,读操作给从服务器)
4、错误日志(error log):记录mysql启动、停止,及服务器运行过程中发生的错误,默认情况下关闭,错误信息被输出到标准错误输出;指定错误日志路径两种方法:1)编辑my.cnf :写入 log-error=[path];2)通过命令: mysqld_safe –user=mysql –log-error=[path] &
显示错误日志的命令:

5、慢查询日志(slow query log):记录执行时间过长的sql,和没有使用索引的查询语句,没成功的不记录;
查慢查询时间:show variables like “long_query_time”,默认10s;
查慢查询日志路径:show variables like “%slow%”;
开启慢日志:set global slow_query_log = 1;
6、一般查询日志(general log):记录服务器接收到的每一个查询或命令,失败的也会记录,开启它会产生不小的开销,默认关闭;
开启general log: set global general_log=on;
查看日志的存放方式:show variables like ‘log_output’;

7、中继日志(relay log)

分库分表

垂直分库:按业务将表分类,分到不同的数据库(如商品放商品库;店铺信放店铺库),没解决单表数据量过大问题
垂直分表:将一个表按字段分成多表(如商品表描述信息较少访问,拆到另一个表,主键ID一样)
水平分库:将一个表的数据按一定规则拆到不同数据库(如店铺ID为单数、偶数的商品存在两个表)
水平分表:在一个数据库内,把同一个表的数据按一定规则拆到多个表中

上亿条数据如何处理
1)分库分表:mysql单表性能瓶颈是百万,按日期拆分成多个,1年以前的拆出去等
2)优化sql和索引
3)读写分离、数据迁移等:主库写从库读
4)增加缓存

并发、 并行

高并发:两方面,同一时刻大量请求访问;大量请求并行访问系统,指标1秒内能处理的请求数量

并发:某个时间段内多个程序间隔一定时间同时运行,由于CPU处理速度非常快,时间间隔处理得当,即可让用户感觉是多个应用程序同时在进行(如听音乐和敲代码)

并行:在某一时刻,真正有多个程序在运行,只在多CPU或一CPU多核的情况中发生。

解决高并发

1)提升机器性能:提升单机,8核到16核,8G到16G;多台机器集群

2)redis缓存:防止多次请求服务器

3)1秒1万,但就是有1秒100万:

     使用mq,将所有请求放入队列,以毫秒计时,排着队处理,需要用户等待一会;

     限流,让流量1万1万的过来,访问入口统一,入口扛不住,使用dns负载均衡,解析域名分发到不同服务器处理

4)静态页面:将静态资源放入CDN中加速访问;

5)代码方面优化:开多线程、能用单例的不频繁的new对象、使用效率高的类,如使用StringBuilder,ArrayList等(StringBuffer 线程安全,StringBuilder 线程不安全,性能远大于StringBuffer)

SQL注入

改造SQL语句达到目的,如 输入实现无帐号登录,用户名输入’or 1 = 1 --
密码不输入,后台验证的SQL变成:
SELECT * FROM user_table WHERE username=‘’ or 1 = 1  -- ’and password=‘’

#{} 防sql注入,会给传参加双引号

${} 可用在动态表名,select * from emp_ ${year}

Redis

Key值类型有string、link、set、order set、hash--基本上就是string
value值类型有string、list、set、zset、hash

string底层是char数组,java String底层是byte数组;

list底层双端链表,链表最大长度为2^32-1;

set 包含字符串的无序集合;hash 包含键值对的无序散列表;

zset 有序集合,存储键值对的散列结构,底层是压缩表ziplist 或 跳表skiplist

        跳表本质:一个多层链表,快速地查询、插入、删除,时间复杂度均为logn;

当redis插入第一个元素 同时满足以下条件,就是创建压缩表ziplist
节点数量<128 (可通过server.zset_max_ziplist_entries设置)
节点的长度<64(可通过server.zset_max_ziplist_value设置)
当选择用ziplist实现zset后,以后插入节点若不满足以上任一条件,就会转为skiplist

redis 大key问题 

redis ke和value类型,值限制为512MB,其他类型限制个数最多为2^32-1

大key情形:

String类型为5MB;List类型列表数量为20000个;
ZSet类型成员数量为10000个;
Hash类型成员数量虽然只有1000个但这些成员的value总大小为100MB;

解决无非就是:首先是监听防止对大Key进行拆分;清理(可用unlink命令

Redis持久化

redis持久化:指在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复时是将快照文件读入内存(因为保存在内存中,断电或者宕机,内存中的数据会全部丢失)。两种持久化方式:RDB和AOF,默认RDB

RDB(Redis DataBase):将内存快照保存在dump.rdb的二进制文件中,可配置持久化策略:save N M,让redis在“N秒内至少有M个改动”才会触发一次rdb持久化操作。也可在redis客户端手动执行save或bgsave命令生成RDB快照

1、数据量大时耗性能,每次持久化要将所有内存数据写入文件,然后替换原有文件

2、可能导致redis宕机的时候丢失最后一次持久化数据,当生成快照策略设置的时间间隔很大

 AOF(Append-Only File):每执行一次写操作命令(读操作不记录),都将该命令追加到appendonly.aof文件中,数据恢复时将写指令从前到后执行一次。通过修改配置文件来使用AOF:# appendonly yes;缺点:比起RDB占用更多的磁盘空间;恢复备份速度要慢;

可以配置三种刷盘策略:

appendfsync always:每次执行写命令都刷盘,非常慢,也非常安全
appendfsync everysec:每秒刷盘一次,兼顾性能和安全(推荐)
appendfsync no:将刷盘操作交给系统,很快,不安全

分布式锁

基于数据库:利用数据库的唯一索引来实现,同一时刻只允许一个竞争者获取锁;创建表,给业务防重id字段加唯一键,加锁时插入一条记录,解锁是删除这条记录

基于缓存:理论上效率最高,因为Redis是纯内存操作,其他两个会涉及磁盘文件IO;利用Redis的setnx key value(setnx 当key不存在时才设置当前key),即加锁

基于Zookeeper:实现原理和Redis类似,在Zookeeper中创建瞬时节点,利用节点不能重复创建的特性来保证排他性。

是否可重入:同一个竞争者,在获取锁后未释放锁之前再来加锁,会加锁失败,因此是不可重入;解决:加锁时判断是否有业务防重ID的记录,如果有且holder_id字段(锁持有者id)和当前竞争者id相同,则加锁成功;

redis也是这样,存在key,再判断key的value是否为当前竞争者id,是返回加锁成功

参考链接:分布式锁的三种实现方式_头未秃的博客-CSDN博客_分布式锁

redis其他应用场景
1、zset做排行榜,比如根据点赞量做人气排行榜(zset:redis直接排序的数据结构)
2、计数器,比如个人主页浏览量统计、收藏、点赞、签到
3、主库,把数据放到缓存中,在数据库不忙的时候异步同步过去

 redis实现数据一致性

1)先更新数据库,再更新缓存

2)缓存延迟双删:先删缓存,再更新数据库,然后延迟几秒再删缓存(怕删更之间又来了个读请求)

3)锁保持强一致性:并发量不大的情况下

4)重试机制:删除缓存失败,对删除操作进行重试

缓存雪崩、击穿、穿透

1、缓存雪崩:大量请求无法在Redis中处理,然后应用将大量请求发送到数据库,导致数据库层压力激增

发生情况:大量的热门缓存同时失效,缓存服务器down机了;

解决办法:1)不设置相同的过期时间;2)做高可用架构,redis可以使用哨兵模式 或 集群模式,避免单节点故障导致整个redis服务不可用;3)做了高可用架构,redis服务还是挂,
需要做服务降级,配置一些默认的兜底数据


2、缓存击穿:某个访问非常频繁的请求无法在Redis处理,然后该请求发送到数据库

发生情况:到过期时间key失效,如大量购买某商品的请求过来

解决办法:1)加锁,限制一次只有一个请求能访问;2)自动续期,或永久


3、缓存穿透:要访问的数据不在缓存,也不在数据库,发生数据缺失

发生情况:1)用户请求的id在缓存中不存在;2)恶意用户伪造不存在的id发起请求

解决办法:1)校验参数,对key做检验; 2)布隆过滤器,也是校验key的高级操作,底层使用bit数组存储数据,数组元素默认值0,第一次初始化时,把数据库中所有存在的key,经过一系列hash算法(比如:三次hash算法)计算,每个key都会计算出多个位置,然后把这些位置上的元素值设置成1;

有用户key请求时,用相同的hash算法计算位置,有1个以上的位置元素值是0,说明该key不存在,拒绝该请求;

存在误判情况(因为hash算法有可能哈希冲突) 和 存在数据更新问题(新加的数据没同步到布隆过滤器,这时候请求该数据,没有该key就会被拒绝)

所以使用布隆过滤器要看实际业务场景,解决了缓存穿透,但同时了带来了新的问题

MongoDB 

1、跨平台,面向文档的数据库,当前 NoSQL 数据库最热门的一种;
2、介于关系数据库和非关系数据库之间,支持的数据结构非常松散,是BSON 格式,可存储较复杂的数据类型(类似 JSON,是对JSON 的扩展,使得JSON更加丰富)
3、关系型:表与表之间存在关系,一对一、一对多、多对多
     非关系型:表与表之间没有关系
4、什么时候用MongoDB:数据量大、写入操作频繁、价值较低(丢一两条数据无所谓)

创建数据库
1)show dbs:显示所有数据(库)列表(备注:创建数据库后,需插一条数据后才会真正创建,才能查询到??,db.runoob.insert({"name":"菜鸟教程"}))
2)use DATABASE_NAME (数据库不存在,则创建,否则切换)
3)MongoDB默认数据库为 test,没有创建新数据库,集合将存放在test数据库

删除数据库 (只删除里面的集合数据,数据库还在)
1)选择要删除的数据库:use runoob
2)db.dropDatabase()

数据库的 集合 操作
1)查看集合:show tables/collections
2)删除集合:db.test_collection.drop()
3)创建集合(类似数据库中的表):db.createCollection("test_collection");
     插入文档时,MongoDB 会自动创建集合:db.runoob.insert({x:10}) (数据库用”db”表示,该数据库存储在data目录中)
     db.runoob.find()
4)集合插入文档:db.col.save(document) 、db.col.insert(document) ,不指定_id字段, save()方法类似于insert()方法。如果指定,则会更新该 _id 的数据;
     插入多条数据:db.collection.insertMany([{"b": 3}, {'c': 4}])
5)集合更新文档:update() 方法

可视化工具: RoboMongo

Python Web 框架三巨头:Flask、Django 和 FastAPI

ClickHouse

1、概述

ClickHouse:属于关系型,用于联机分析(OLAP)的列式数据库管理系统,列式结构具备一种天然优势,就是做统计分析,聚类分析;安装不支持windows

 行式数据库,处于同一行中的数据被物理的存储在一起

RowWatchIDJavaEnableTitleGoodEventEventTime
#0893543506621Investor Relations12016-05-18 05:19:20
#1903295099580Contact us12016-05-18 08:10:20

列式数据库,来自同一列的数据被存储在一起,来自不同列的值被单独存储

Row:#0#1#2#N
WatchID:893543506629032950995889953706054...
JavaEnable:101...
Title:Investor RelationsContact usMission...
GoodEvent:111...
EventTime:2016-05-18 05:19:202016-05-18 08:10:202016-05-18 07:38:00...
列式、行式数据库分析: 什么是ClickHouse? | ClickHouse Docs
OLAP场景的关键特征:
    绝大多数是读请求
    数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
    已添加到数据库的数据不能修改。
    对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
    宽表,即每个表包含着大量的列
    查询相对较少(通常每台服务器每秒查询数百次或更少)
    对于简单查询,允许延迟大约50毫秒
    列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
    处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
    事务不是必须的
    对数据一致性要求低
    每个查询有一个大表。除了他以外,其他的都很小。
    查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM(随机存储器)中

2、产生背景

物联网IOT时代来临,IOT设备感知和报警存储的数据越来越大,大数据分析成了非常重要的环节。把各种开源框架、工具、库、平台人工整合到一起所需工作之复杂,是大数据领域开发和大数据分析工程师常有的抱怨之一。

3、发展历史

Yandex--俄罗斯的百度,2016年6月15日开源了一个数据分析的数据库--ClickHouse,这个列式存储数据库的跑分要超过很多流行的商业MPP数据库软件,例如Vertica--MPP列式存储商业数据库的高性能代表,Facebook就购买了Vertica数据用于用户行为分析

4、ClickHouse应用场景

自从ClickHouse2016年6月15日开源后,ClickHouse中文社区随后成立。中文开源组开始以易观,海康威视,美团,新浪,京东,58,腾讯,酷狗音乐和俄罗斯开源社区等人员组成

目前国内社区火热,各个大厂纷纷跟进大规模使用:
今日头条 内部用ClickHouse来做用户行为分析,内部一共几千个ClickHouse节点,单集群最大1200节点,总数据量几十PB,日增原始数据300TB左右。
腾讯内部用ClickHouse做游戏数据分析,并且为之建立了一整套监控运维体系。
携程内部从18年7月份开始接入试用,目前80%的业务都跑在ClickHouse上。每天数据增量十多亿,近百万次查询请求。
快手内部也在使用ClickHouse,存储总量大约10PB, 每天新增200TB, 90%查询小于3S。

#可以应用以下场景:
1.电信行业用于存储数据和统计数据使用。
2.新浪微博用于用户行为数据记录和分析工作。
3.用于广告网络和RTB,电子商务的用户行为分析。
4.信息安全里面的日志分析。
5.检测和遥感信息的挖掘。
6.商业智能。
7.网络游戏以及物联网的数据处理和价值数据分析。
8.最大的应用来自于Yandex的统计分析服务Yandex.Metrica,类似于谷歌Analytics(GA),或友盟统计,小米统计,帮助网站或移动应用进行数据分析和精细化运营工具,据称Yandex.Metrica为世界上第二大的网站分析平台。ClickHouse在这个应用中,部署了近四百台机器,每天支持200亿的事件和历史总记录超过13万亿条记录,这些记录都存有原始数据(非聚合数据),随时可以使用SQL查询和分析,生成用户报告。

5、启动

5.1 启动服务端:sudo service clickhouse-server start 或 sudo /etc/init.d/clickhouse-server start

5.2 服务端日志目录:/var/log/clickhouse-server

5.3 启动交互式客户端:clickhouse-client

若要多行查询:clickhouse-client -m  或  clickhouse-client --multiline
启动后,可执行简单命令测试:SELECT 'hello world';

5.4 服务端启动后,不启动交互式客户端,则利用clickhouse-client连接到服务端,运行一些测试查询:

clickhouse-client --query="SELECT 'hello world'";
clickhouse-client --query='SELECT 123'

6、命令

6.1 创建数据库testDB(包含默认数据库:default、system):CREATE DATABASE IF NOT EXISTS testDB

6.2 创建表

必须指定三个关键的事情:
要创建的表的名称;
表结构,例如:列名和对应的数据类型--https://www.cnblogs.com/wshenjin/p/13072989.html
表引擎及其设置,这决定了对此表的查询操作是如何在物理层面执行的所有细节;
【表引擎(table engine):不同的存储引擎提供不同的存储机制、索引方式、锁定水平等功能,也可以称之为表类型。如MySQL的InnoDB和MyISAM存储引擎,ClickHouse提供了丰富的表引擎(如MergeTree、CollapsingMergeTree),作用:
    决定表存储在哪里以及以何种方式存储
    支持哪些查询以及如何支持
    并发数据访问
    索引的使用
    是否可以执行多线程请求
    数据复制参数

CREATE TABLE testDB.hits_v1
(
    `WatchID` UInt64,
    `JavaEnable` UInt8,
    `Title` String,
     ...
    `ShareURL` String,
    `ShareTitle` String,
    `ParsedParams` Nested(
        Key1 String,
        Key2 String,
        Key3 String,
        Key4 String,
        Key5 String,
        ValueDouble Float64),
    `IslandID` FixedString(16),
    `RequestNum` UInt32,
    `RequestTry` UInt8
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID)

6.3 插入数据(导入数据集的方式)

下载表数据集:curl https://datasets.clickhouse.tech/hits/tsv/hits_v1.tsv.xz | unxz --threads=`nproc` > hits_v1.tsv
导入数据:clickhouse-client --query "INSERT INTO testDB.hits_v1 FORMAT TSV" --max_insert_block_size=100000 < hits_v1.tsv

ClickHouse设置参数,如--max_insert_block_size。查找可用设置参数,查询system.settings表:
SELECT name, value, changed, description FROM system.settings WHERE name LIKE '%max_insert_b%' FORMAT TSV

6.4 插入数据(sql方式)

CREATE TABLE testDB.test_table (
    device_id FixedString(36),
    metric String,
    time UInt64,
    value Float64
)
ENGINE = Memory;

insert into test_table(device_id,metric,time,value) VALUES('10001','惠普','192133',1);

6.5 检查表导入是否成功:SELECT * FROM testDB.hits_v1

6.6 删除、更新数据:

ALTER TABLE test_table DELETE WHERE metric='metric_1';
ALTER TABLE test_table UPDATE metric='神州' WHERE device_id='10001';

历史:
在OLAP数据库中,可变数据(Mutable data)通常是不被欢迎的,Clickhouse也是如此,早期版本不支持UPDATE和DELTE操作。在Clickhouse 1.1.54388版本之后才支持UPDATE和DELETE操作,适用于MergeTree引擎,并且这种操作方式是异步的(asynchronous),但是在一些交互场景下很难使用。在一些场景下用户需要修改了数据即刻可以看到。这种实时更新(real-tiime update)在2020年4月可以在clickhouse中实现了。
在clickhouse 开源的2016年ClickHouse当时不支持数据修改。为了模拟更新,只能使用特殊的插入结构,并且数据必须由分区删除。
在GDPR要求的压力下,ClickHouse团队在2018年发布了UPDATE和DELETE。这些异步的,非原子的更新被实现为ALTER TABLE UPDATE语句,并且有可能shuffle 很多数据。当不需要立即知道结果时,这对于批量操作和不频繁更新很有用。

6.7 函数语法:select toYear(toDate('2018-12-11')) --返回2018

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值