青海兴远建设工程有限公司网站,测评网站怎么做,如何建设一个国外网站,wordpress内网外网访问不了目录
一、ClickHouse高性能查询原因-稀疏索引 二、ClickHouse高性能写入-LSM-Tree存储结构
什么是LSM-Tree 三、ClickHouse的常见注意事项和异常问题排查 一、ClickHouse高性能查询原因-稀疏索引
密集索引: 在密集索引中#xff0c;数据库中的每个键值都有一个索引记录数据库中的每个键值都有一个索引记录可以加快搜索速度但需要更多空间来存储索引记录本身索引记录包含键值和指向磁盘上实际记录的指针。 mysql中Innodb引擎的主键就是密集索引 稀疏索引: 在稀疏索引中不会为每个关键字创建索引记录而是为数据记录文件的每个存储块设一个键-指针对存储块意味着块内存储单元连续 案例 Mysql的MyISAM引擎里面 使用均为稀疏索引 Mysql的Innodb引擎里面如果有主键则主键为密集索引 Kafka里面的索引文件也是采用稀疏索引进行构造消息索引 ClickHouse的合并树MergeTree引擎是稀疏索引默认index_granularity设置8192新版本的提供了自适应粒度大小的特性 建表语句最后加这个可以调整 SETTINGS index_granularity 8192 结论: ClickHouse一级索引就是【稀疏索引】可以大幅减少索引占用的空间 默认的索引力度8192假如1亿行数据只需要存储12208行索引占用空间小clickhouse中一级索引的数据是常驻内存的取用速度极快 稀疏索引所占空间小并且插入和删除时所需维护的开销也小缺点是速度比密集索引慢一点 密集索引空间占用多比稀疏索引更快的定位一条记录缺点就是会占用较多的空间 不变思想时间换空间、空间换时间 二、ClickHouse高性能写入-LSM-Tree存储结构
先明白一个测试数据 磁盘顺序读写和随机读写的性能差距大概是1千到5千倍之间
连续 I/O 顺序读写磁头几乎不用换道或者换道的时间很短性能很高比如0.03 * 2000 MB /s 随机 I/O 随机读写会导致磁头不停地换道造成效率的极大降低0.03MB/s
ClickHouse中的MergeTree也是类LSM树的思想所以我们也需要了解LSM树
充分利用了磁盘顺序写的特性实现高吞吐写能力数据写入后定期在后台Compaction 在数据导入时全部是顺序append写在后台合并时也是多个段merge sort后顺序写回磁盘 官方公开benchmark测试显示能够达到50MB-200MB/s的写入吞吐能力按照每行100Byte估算大约相当于50W-200W条/s的写入速度
什么是LSM-Tree 全称 Log-Structured Merge-Tree 日志结构合并树但不是树而是利用磁盘顺序读写能力实现一个多层读写的存储结构 是一种分层有序面向磁盘的数据结构核心思想是利用了磁盘批量的顺序写要远比随机写性能高出很多 大大提升了数据的写入能力但会牺牲部分读取性能为代价 HBase、LevelDB、ClickHouse这些NoSQL存储都是采用的类LSM树结构 在 NoSQL 系统里非常常见基本已经成为必选方案, 为了解决快速读写的问题去设计的 可以分两个部分理解
Log-Structured日志结构的打印日志是一行行往下写不需要更改只需要在后边追加就好了 Merge-tree 合并就是把多个合成一个自上而下 LSM-tree 是一个多层结构就更一个喷泉树一样上小下大
专门为 key-value 存储系统设计的最主要的就两个个功能
写入putkv 查找 getk得到v 首先是内存的 C0 层保存了所有最近写入的 kv这个内存结构是有序的且可以随时原地更新同时支持随时查询
接下去的 C1 到 Ck 层都在磁盘上每一层都是一个有序的存储结构
降低一点读性能通过牺牲小部分读性能换来高性能写 写入流程 put 操作首先追加到写前日志Write Ahead Log然后加到C0 层 当 C0 层的数据达到一定大小就把 C0 层 和 C1 层合并这个过程就是Compaction合并 合并出来的新的C1 会顺序写磁盘替换掉原来的C1 当 C1 层达到一定大小会和下层继续合并合并后删除旧的留下新的 查询流程: 最新的数据在 C0 层最老的数据在 Cn 层 查询也是先查 C0 层如果没有要查的数据再查 C1逐层查下去直到最后一层 缺点: 读放大: 读取数据时实际读取的数据量大于真正的数据量在LSM树中需要先在C0查看当前key是否存在不存在继续从Cn层中寻找 写放大: 写入数据时实际写入的数据量大于真正的数据量在LSM树中写入时可能触发Compact操作导致实际写入的数据量远大于该key的数据量 三、ClickHouse的常见注意事项和异常问题排查
注意点一: 查询要使用的列避免select * 全部字段浪费IO资源
注意点二: 避免大量的小批量数据插入更新操作会导致分区过多 每次插入1条产生了一个分区大量写入产生大量临时分区和合并操作浪费资源
注意点三: JOIN操作时一定要把数据量小的表放在右边无论是Left Join 、Right Join还是Inner Join右表中的每一条记录到左表中查找该记录是否存在所以右表必须是小表
注意点四: 批量写入数据时控制每个批次的数据中涉及到的分区的数量无序的数据导致涉及的分区太多建议写入之前最好对需要导入的数据进行排序
注意点五: 写入分布式表还是本地表? 建议数据量不大写入本地表和分布式表都行 分布式表不存储数据本地表存储数据的表
大量数据日新增500万行以上分布式表在写入时会在本地节点生成临时数据会产生写放大所以会对CPU及内存造成一些额外消耗服务器merge的工作量增加, 导致写入速度变慢
数据写入默认是异步的可以开启同步写但性能会影响先在分布式表所在的机器进行落盘, 然后异步的发送到本地表所在机器进行存储中间没有一致性的校验短时间内可能造成不一致且如果分布式表所在机器时如果机器出现down机, 会存在数据丢失风险。
建议大数据量尽量少使用分布式表进行写操作可以根据业务规则均衡的写入本地表 必须用的话尽量只用读因为写分布式表对性能影响非常大
注意点六: 单sql查询可以压榨CPU 但并发多条查询则不是很强 一个分区查询占据一个CPU业务需要查询表的多个分区可以多个CPU并行处理
注意点七: 没有完整的事务支持不支持Transaction OLAP类业务由于数据量非常大建议数据批量写入尽量避免数据更新或少更新
注意点八: 在分布式模式下ClickHouse会将数据分为多个分片并且分布到不同节点上有哪种分片策略
ClickHouse提供了丰富的sharding策略让业务可以根据实际需求选用
random随机分片:写入数据会被随机分发到分布式集群中的某个节点上 constant固定分片:写入数据会被分发到固定一个节点上 hash column value分片按照某一列的值进行hash分片
常见异常问题: 错误码 300Too many parts 写入频率过快使用了不合理的分区键导致总的 part 数目太多直接拿精确到秒的 timestamp 来作为分区键来进行分区GG了。 错误码252Too many partitions for single INSERT block (more than 100),同一批次写入里包括大于100个分区值clickhouse认为这样会存在性能问题
让数据是按照天/小时分区的一批数据里的日期跨度为一年单次插入可能产生365个分区导致后台异步合并数据出现问题也避免跨度过大
解决方案单批次写入数据要控制写入分区过多
参数max_partitions_per_insert_block 限制单个插入块中的最大分区数默认是100