您可以使用以下方式,提高日志查询分析的速度。
增加Shard数量或开启SQL独享版
增加Shard可以提升读写能力,但只对新写入的数据生效。Shard表示计算资源,Shard越多,计算越快,您需要保证平均每个Shard扫描的数据不多于5000万条。您可以通过分裂Shard,增加Shard数量。具体操作,请参见分裂Shard。Shard的计费信息,请参见活跃Shard租用费用。
SQL独享版支持更多的分析操作并发数、更多的扫描数据量。
缩减查询的时间范围和数据量
时间范围越大,查询越慢。
适当缩短查询的时间范围可以更快地完成计算。
数据量越大,查询越慢。
请尽量减少查询的数据量。
多次重复查询
当查询不精确时,可以尝试多次重复查询。每次查询时,底层加速机制会充分利用已有的结果进行分析,因此多次查询可以使结果更加精确。
优化SQL分析语句
计算时间较长的查询分析语句具备如下特点。
使用GROUP BY语法基于字符串列进行分组统计。
使用GROUP BY语法基于多列(大于5列)进行分组统计。
在SQL分析语句中有生成字符串的操作。
您可以通过如下方法优化分析语句。
尽量避免生成字符串的操作。
例如使用date_format函数生成格式化的时间戳,导致查询效率低。针对时间戳的计算,建议使用date_trunc或者time_series函数进行计算。示例如下:
* | select date_format(from_unixtime(__time__) , '%H_%i') as t, count(1) group by t
尽量避免对字符串列进行分组统计。
使用GROUP BY语法基于字符串列进行分组统计,会导致大量的Hash计算,这部分计算量占据整体计算量的50%以上。示例如下:
查询和分析语句(速度快)
* | select count(1) as pv , from_unixtime(__time__-__time__%3600) as time group by __time__-__time__%3600
查询和分析语句(速度慢)
* | select count(1) as pv , date_trunc('hour',__time__) as time group by time
上述两条查询分析语句都是计算每小时的日志条数。第二条语句先把时间戳转化成字符串格式(例如2021-12-12 00:00:00),然后对这个字符串列进行分组统计。第一条语句对时间整点值进行计算,并且通过分组统计后再将时间戳转化为字符串格式。
基于多列进行分组统计时,把字典大的字段放在前面。
例如字段的值有13个,uid字段的值有1亿个,则建议在GROUP BY子句中将uid字段放在前面。示例如下:
查询和分析语句(速度快)
* | select province,uid,count(1) group by uid,province
查询和分析语句(速度慢)
* | select province,uid,count(1) group by province,uid
使用估算函数。
估算函数的性能比精算函数的好。估算会损失一定的精确度,用于达到快速计算的效果。示例如下:
查询和分析语句(速度快)
* |select approx_distinct(ip)
查询和分析语句(速度慢)
* | select count(distinct(ip))
在SQL分析语句中指定获取需要的列,尽量不要读取所有列。
在SQL分析语句中,尽量只读取需要参与计算的列。如果要获取所有列,请使用查询语法。示例如下:
查询和分析语句(速度快)
* |select a,b c
查询和分析语句(速度慢)
* |select *
不是用于分组的列,尽量放在聚合函数中。
例如userid与用户名必定是一一对应的,您只需使用GROUP BY语法对userid进行分组统计即可。示例如下:
查询和分析语句(速度快)
* | select userid, arbitrary(username), count(1) group by userid
查询和分析语句(速度慢)
* | select userid, username, count(1) group by userid,username
尽量避免使用IN语法
尽量避免在分析语句中使用IN语法,您可以在查询语句中使用OR语法代替。示例如下:
查询和分析语句(速度快)
key: a or key: b or key: c | select count(1)
查询和分析语句(速度慢)
* | select count(1) where key in ('a','b')