性能类问题
更新时间:2020-03-20
索引建立有什么建议吗?
云数据库 FusionDB 中支持两类索引,分别是B树索引和位图索引。但在云数据库 FusionDB 中不推荐使用索引,原因有三个:
- 云数据库 FusionDB 一般需要访问大数据集,并且云数据库 FusionDB 可以通过分区、并行执行等方式提升查询效率。索引的作用不能有效发挥。
- 拖慢数据入库的性能。因为数据仓库经常需要导入大量数据,这个时候需要调整索引结构,导入速度极差。
- 需要占用额外的磁盘存储空间。 因此,在OLAP场景中的大多数情况不建议使用。比如频繁插入更新的字段、重复度高的字段均不建议创建索引。 少数场景可以考虑建立索引:比如经常需要按照类似主键的字段从几十亿的数据中就查数百条记录,这种场景,索引能够有效地提升查询性能;或者有少数表希望能像OLTP场景记录信息,数据量较小,可以创建主键索引保证数据的唯一。
怎样选择表的分布键?
在考虑分布策略的时候首要原则就是要保证数据在每个节点尽可能分布均匀,其次是尽可能减少数据重分布操作带来的资源消耗。 所以提出了以下三个原则。
- 如果后续的SQL没有group by或者join等会引起数据重分布的操作,此时选择随机分布策略;
- 如果需要经常做group by或者join这样的操作,我们就要慎重考虑分布键,先考虑下做join操作的联合建或者group by字段是否会可以使数据分布均匀。
- 如果找不到这种分布键,就选择随机分布。 还有一点需要特别注意的是,如建表没有指定具体的分布策略,GP将会默认选择主键作为分布键,如果没有指定主键,将会默认选择第一列作为分布键。很容易导致严重的数据倾斜。
对于建表有什么建议呢?
- 分布键选取正确,按照上个问题进行慎重选择。
- 存储模型的选择:一种是默认类型的Heap表,Heap表可以进行循环的Update、Delete和单行insert操作,也可以进行并发的Update、Delete、Insert;另一种是Appendonly表,Appendonly表用于初始加载数据后很少更新,并且后续只是进行批量插入的操作。
- 行存&列存的选择:默认使用行式存储。行存适合于传统的频繁进行更新和插入的交易类型的事务,和对于常用每个Query都涉及记录中的很多列的情况。如果Select列表和Where条件需要数据表中大多数列,则此数据表采用行存最适合;列存适用于宽表。1)对于经常需要对小部分列做聚合计算的场景。2)有单个列经常被更新并且不修改其他列的场景。
- 是否数据压缩:考虑到随着业务的发展,数据量存储的压力,对应数据量大一些的冷数据可以考虑采用压缩。只要压缩级别不是太高,都可以有效的降低存储空间,并且对查询性能不会造成太大的影响。常用的压缩选项是zlib5,但是如果提升到zlib9,可能压缩效果会提升10%+,但访问性能会成倍下降。
- 是否分区:云数据库 FusionDB 的分区原理与其他数据库无异,合适的分区可以减少磁盘I/O操作加速查询效率,但是建议是不要把表分区设计的过于零碎,一般来说一个表的分区数量,几十个就差不多了,不宜过多,对应冷数据可以做分区合并并压缩存储已节省存储空间。分区之间数据无需均匀。
有哪些SQL优化建议?
- 数据类型转换,必须要显式转换CAST ('string' as 类型);
- 用LEFT JOIN代替 NOT IN;
- 尽量使用外连接的方式代替嵌套子查询;
- 查询记录数过多时,限制返回条数,如limit 100;
- 两个表之间的join字段类型必须一致;
- join字段尽可能是表的分布键,以避免数据重分布;
- 使用group by代替distinct;
- 尽量避免创建索引,且索引对于多表的join是没有性能提升的。