南大通用GBase 8a SQL的简要优化步骤:
1、获取长sql
Select sql_text from gclusterdb.audit_log_express where TIMESTAMPDIFF(second,start_time,end_time) >2000;
需要gclusterdb.audit_log_express表的权限,2000代表执行时间长度为2000的长SQL,可以在每个集群执行后导出。
也可按时间查询,gclusterdb.audit_log_express表结构如下:
gbase> desc audit_log_express;
+-------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| hostname | varchar(64) | YES | | NULL | |
| thread_id | int(11) | YES | | NULL | |
| taskid | bigint(20) | YES | | NULL | |
| start_time | datetime | YES | | NULL | |
| uid | bigint(20) | YES | | NULL | |
| user | varchar(16) | YES | | NULL | |
| host_ip | varchar(32) | YES | | NULL | |
| query_time | time | YES | | NULL | |
| rows | bigint(20) | YES | | NULL | |
| table_list | varchar(4096) | YES | | NULL | |
| sql_text | varchar(8192) | YES | | NULL | |
| sql_type | varchar(16) | YES | | NULL | |
| sql_command | varchar(32) | YES | | NULL | |
| operators | varchar(256) | YES | | NULL | |
| status | varchar(16) | YES | | NULL | |
| conn_type | varchar(16) | YES | | NULL | |
+-------------+---------------+------+-----+---------+-------+
2、判断表类型
根据步骤1获取到的SQL,进行逐个优化。
1)把SQL中的所有表找出来
2)gccli登录集群通过show create table 看表类型,或通过监控工具查看表类型和分布列,初步判断是否存在随机分布表,是否hash列选取有问题的表,是否存在大数据量(超过100万)建成复制表的情况,有问题进行整改,建议把所有随机分布表都改为hash分布表。
建Hash分布列的原则基本如下:
Ø尽量选择count(distinct)值大的列做Hash分布列,让数据均匀分布。
Ø优先考虑大表间的JOIN,尽量让大表JOIN条件的列为Hash分布列(相关子查询的相关JOIN也可以参考此原则),以使得大表间的JOIN可以直接分布式执行。
Ø其次考虑GROUP BY,尽量让GROUP BY带有Hash分布列,让分组聚合一步完成。
Ø通常是等值查询的列,并且使用的频率很高的应考虑建立为hash分布列
注意事项:
Øhash分布键只能选择 1 个
Øhash分布键只能选择数值和字符串类型的列
Ø作为hash分布列的列不能进行update
Ø尽量保持hash join的等值关联列在类型定义上完全相同,如char和varchar类型进行关联,可能出现结果为空情况,原因是char型
3)gccli登录集群,根据筛选条件判断各表数据量大小,判断结果集大小是否合理,是否存在漏写筛选条件的情况。
4)如果经常关联的列不是hash列,尽可能调整一致。
3、判断是否存在笛卡尔积
步骤2完成后,需要根据join关联列和筛选条件判断每个表的关联列是否存在重复值,重复值会导致笛卡尔积,大大影响SQL性能和集群整体性能。
一般使用如下语句,判断重复值前十条即可,如果有问题,前十条也能很明显会出大量重复值数据。
select 列明,count(1) from 表名 group by 列明 order by列明 desc limit 10;
4、其它优化点
1)避免使用select * from ,尤其是子查询,需要查询哪些列就显式写明那些列
2)尽量避免where条件中对列进行函数运算再进行比较,加函数会造成智能索引失效,sql性能降低。
例如:某现场原始sql为:where substr(product_no, 2, 1) in ('3', '4', '5', '8'),智能索引失效,性能非常低;
改写为: where (product_no like '13%' or product_no like '14%' or product_no like '15%' or product_no like '18%')'
3)如果数据量小(千万级)执行时间很长,按上述步骤检查没问题,可以考虑数据分布不均衡的问题,需要查看各节点使用到的表是否有偏离
4)dblink时间长的表尽量按日期去抽取
5)如果join关联的右表使用子查询可以大量减少结果集,可以考虑使用子查询过滤后再进行join。
















