美文网首页
vertica数据库SQL编写规范

vertica数据库SQL编写规范

作者: mr_酱 | 来源:发表于2019-02-13 10:05 被阅读13次

    SELECT 查询优化

    【强制】明确查询的字段,禁止使用select *
    说明:防止表结构变更导致程序异常;明确字段,避免读取所有字段列(列式数据库特性)。
    【强制】表关联时,改变表驱动顺序,使用小表驱动大表
    【强制】禁止使用select …for update
    说明:导致数据行被锁,容易造成死锁,影响业务正常运行。
    【推荐】多表关联或排序所涉及的字段建议projection中优先进行order by排序
    【强制】禁止出现隐式转换,保持SQL中变量类型与字段类型一致
    示例:条件语句中数据类型以传入参数为准。user_id定义为int型,在程序中使用user_id=’1’,就会发生隐式转换,将user_id转换成varchar类型,影响数据库性能,因此应使用user_id=1。
    【规则】where条件所涉及的过滤字段尽量选择基数低的列放前面
    说明:过滤字段选用高选择性的字段
    【规则】禁止对“=”左侧字段使用函数、运算,避免在join、group by中使用函数,这样可以让优化器能更好的发挥作用
    【规则】避免使用 not、<>、is null, is not null条件
    【规则】like子句尽量前置匹配,前置不加%,like区分大小写,ilike不区分大小写
    说明:“%”前缀模糊匹配效率低
    【规则】order by 字段顺序尽量与projection中order by顺序保持一致
    说明:projection中已经排序过的数据
    【推荐】多用=操作;>,<操作转换为>=,<=
    说明:“=”号操作可直接定位到相应的位置,>、<操作需要再移一位才能定位
    【推荐】减少无意义的order by、group by操作
    示例:
    select name,val from tabA where userid in (select user_id from tabB order by user_id);
    select user_id from tabB order by rand()
    【推荐】尽可能使用where条件替代having子句
    说明:SQL语句中先执行where后执行having,过滤的结果越多,group by的代价越小
    【推荐】不在where 条件中使用中文过滤数据
    说明:例如where prov_name=‘全国’可以替换为where prov_code=‘999’。
    【推荐】优先使用projection中的order by字段
    【参考】修改业务逻辑,减少大结果集的group by或order by

    INSERT 插入数据优化

    【规则】insert时建议指定字段名,避免字段顺序变动后数据插入错误
    【强制】当需要插入大量数据时,可以使用copy方式装载,避免执行大量insert语句
    【强制】大量数据装载时,使用direct直接路径加载避免占用wos空间
    【推荐】create table as select时,可以使用copy_table函数提高数据复制效率

    UPDATE 更新优化

    【强制】禁止update语句无where条件
    【强制】update语句会造成表级别的X型锁,update操作后需及时提交
    【强制】大量数据修改时(100MB数据以上),使用direct直接路径加载避免占用wos空间

    DELETE 删除优化

    【强制】禁止delete语句无where条件,无where条件的delete语句,改写成truncate语句。
    【规则】删除大量数据时(百万数据量),使用direct直接路径加载避免占用wos空间;
    【规则】delete where方式删除的数据量达到10万级别以上的,delete之后使用执行purge_table操作,示例select purge_table('schema_name.table_name');。

    筛选与子查询

    由于数据仓库数据量大,要尽量避免执行全表扫描的动作,所以在SQL中要使用筛选条件或子查询。考虑到SQL的执行效率,筛选条件中要有分区字段。

    关联

    在使用SQL处理数据的过程中,经常会执行表和表之间关联的动作,常用的关联有:内连接、左连接、右连接、全连接。
    考虑到SQL书写的复杂度和执行效率,一个SQL语句中关联表的数量不能超过5个,处理逻辑确实需要多个表关联的,可以拆分借助临时表进行处理。
    在使用关联时需遵循以下原则:

    • 小结果集驱动大结果集
    • 保证关联表的连接字段都提前排序
    • 合理设计segmented分布,合理的数据分片会避免大量问网络交换
    • Hash Join策略中,小表(inner表,驱动表)会放入内存hash散列,然后再逐条扫描大表(Outer表,被驱动表),查看是否能匹配上
    • 两张大表进行关联,可以将两张表的Protection按照关联字段预先排好序,并按相同的字段在节点间分段,那么优化器会选择更有效率的Merge Join
    • join语句中关联键不使用trim、to_char等函数做处理,特别是在已优化为merge join的情况下,关联键再做函数处理后,查询计划会变为hash join。
    • 举例:
    1、左连接 LEFT JOIN
    select a.statis_date, a.prov_code, a.col_name 
        from 用户名.表名 a
            left join (select user_id 
                    from 用户名.表名  
                    where statis_date=’20181219’
                    ) b on a.user_id=b.user_id
        where a.statis_date=’20181219’;
    
    2、右连接 RIGHT JOIN
    Select b.user_id from csapdws.tb_dws_ct_86hl_xxx_day a
    right join (select user_id from csapdws.tb_dws_ct_86hl_yyy_day  
    where statis_date=’20181219’) b on a.user_id=b.user_id
    where a.statis_date=’20181219’;
    
    3、内连接 INNER JOIN
    select a.* form table_a a inner join table_b  b on a.name_id =b.name_id
    where a.statis_date=’20181219’and b.statis_date=’20181219’;
    
    4、全连接 FULL OUTER JOIN
    FULL OUTER JOIN 产生表A和表B的并集。但是需要注意的是,对于没有匹配的记录,则会以NULL做为值,可以使用IF NULL 判断。
    select a.*,b.* from table_a  a full outer join table_b  b on a.name_id =b.name_id;
    where a.statis_date=’20181219’and b.statis_date=’20181219’;
    

    表数据清理

    【强制】禁止delete语句无where条件,无where条件的delete语句,改写成truncate语句。
    【规则】删除大量数据时(百万数据量),使用direct直接路径加载避免占用wos空间;
    【规则】delete where方式删除的数据量达到10万级别以上的,delete之后使用执行purge_table操作示例select purge_table('schema_name.table_name');
    【规则】分区表采用drop partition;
    【规则】中间表采用temporary table;
    【规则】全表清空数据使用truncate table;
    【规则】必须使用delete where方式的,按照规范使用direct hint;delete where方式删除的数据量达到10万级别以上的,delete之后使用执行purge_table操作,示例select purge_table('schema_name.table_name');
    举例:

        taskPosition="清空统计期结果表"
        verticasql = []
        verticasql.append('''select drop_partition('用户名.表名', '%(ARG_OPTIME)s')'''% vars())
    VerticaExe(verticasql, name, verticaschema, dates,taskPosition)
    taskPosition="插入结果表数据 - 系统呼叫量汇总"
    verticasql = []
    verticasql.append('''
            insert /*+direct*/ into csapdw.tb_dw_ct_86hl_system_call_list_day
            (statis_date,
                   prov_code,
            ''' % vars() )
        VerticaExe(verticasql, name, verticaschema, dates,taskPosition)
    

    相关文章

      网友评论

          本文标题:vertica数据库SQL编写规范

          本文链接:https://www.haomeiwen.com/subject/edfvjqtx.html