- 增加更多shard。
- 缩短时间范围和数据量。
- 多次重复查询。
- 优化查询的SQL。
增加更多shard
缩减查询的时间范围和数据量
- 时间范围越大,查询越慢。如果您查询1年的时间,或者查询1个月的时间。 计算是按天完成的,所以,适当的缩短时间可以更快完成计算。
- 数据量越大,查询越慢。请尽量减少查询的数据量。
多次重复查询
当查询不精确时,可以尝试多次重复查询。每次查询时,底层加速机制会充分利用已有的结果进行分析。所以,多次查询可以使结果更加精确。
优化query
- 对字符串列进行group by。
- 对多列(大于5列)字段进行group by。
- 在SQL中有生成字符串的操作。
- 尽量避免生成字符串的操作
- 使用date_format函数生成格式化的时间戳,导致查询效率低下。
* | select date_format(from_unixtime(__time__) , '%H_%i') as t, count(1) group by t
- 使用substr生成字符串。 对于这类时间戳函数,建议使用date_trunc或者time_series函数进行分析。
- 使用date_format函数生成格式化的时间戳,导致查询效率低下。
- 尽量避免对字符串列进行GROUP BY计算
对字符串进行GROUP BY,会导致大量的hash计算,这部分计算量往往会占据整体计算的50%以上。例如:
Query 1 和Query 2都是计算每小时的日志count数,但是Query 1 首先把时间转化成字符串,例如2017-12-12 00:00:00, 然后对这个字符串进行GROUP BY。 Query 2是先对时间整点值进行计算,GROUP BY计算后才会转化成字符串类型。所以在执行效率上,Query 2更佳。* | select count(1) as pv , date_trunc('hour',__time__) as time group by time * | select count(1) as pv , from_unixtime(__time__-__time__%3600) as time group by __time__-__time__%3600
- GROUP BY多列时,把字典大的字段放在前面
例如,province有13个,用户有1亿。
快: * | select province,uid,count(1)groupby province,uid 慢: * | select province,uid,count(1)groupby uid,province
- 使用估算函数
估算函数的性能要比精确计算好很多。估算会损失一些可接受的精确度,来达到快速计算的效果。
快: * |select approx_distinct(ip) 慢: * | select count(distinct(ip))
- 在SQL中获取需要的列,尽量不要读取所有列
获取所有列,请使用查询语法。在SQL计算时,尽量只读取需要参与计算的列,可以加快计算。
快 : * |select a,b c 慢 :* |select*
- 非group by的列,尽量放到聚合函数中
例如,userid,用户名,必定是一一对应的,我们只需要按照userid进行group by即可。
快: * | select userid, arbitrary(username), count(1)groupby userid 慢: * | select userid, username, count(1)groupby userid,username
- 避免使用in语法
尽量避免在SQL中使用in语法,而应该把in语法用搜索的or语法代替。
快:key : a or key :b or key:c | select count(1) 慢:* | select count(1) where key in ('a','b')