将时间戳转字符串
format_datetime(from_unixtime(time / 1000), 'yyyy-MM-dd HH:mm:ss')
多多使用WITH语句
使用Presto分析统计数据时,可考虑把多次查询合并为一次查询,用Presto提供的子查询完成。
这点和我们熟知的MySQL的使用不是很一样。例如:
WITH subquery_1 AS (
SELECT a1, a2, a3
FROM Table_1
WHERE a3 between 20180101 and 20180131
), /*子查询subquery_1,注意:多个子查询需要用逗号分隔*/
subquery_2 AS (
SELECT b1, b2, b3
FROM Table_2
WHERE b3 between 20180101 and 20180131
) /*最后一个子查询后不要带逗号,不然会报错。*/
SELECT
subquery_1.a1, subquery_1.a2,
subquery_2.b1, subquery_2.b2
FROM subquery_1
JOIN subquery_2
ON subquery_1.a3 = subquery_2.b3;
查询SQL优化
- 只选择使用必要的字段
由于采用列式存储,选择需要的字段可加快字段的读取、减少数据量。避免采用*读取所有字段。
[GOOD]: SELECT time,user,host FROM tbl
[BAD]: SELECT * FROM tbl
- 过滤条件必须加上分区字段
对于有分区的表,where语句中优先使用分区字段进行过滤。acct_day是分区字段,visit_time是具体访问时间
[GOOD]: SELECT time,user,host FROM tbl where acct_day=20171101
[BAD]: SELECT * FROM tbl where visit_time=20171101
- Group By语句优化
合理安排Group by语句中字段顺序对性能有一定提升。将Group By语句中字段按照每个字段distinct数据多少进行降序排列。
[GOOD]: SELECT GROUP BY uid, gender
[BAD]: SELECT GROUP BY gender, uid
- Order by时使用Limit
Order by需要扫描数据到单个worker节点进行排序,导致单个worker需要大量内存。如果是查询Top N或者Bottom N,使用limit可减少排序计算和内存压力。
[GOOD]: SELECT * FROM tbl ORDER BY time LIMIT 100
[BAD]: SELECT * FROM tbl ORDER BY time
- 使用Join语句时将大表放在左边
Presto中join的默认算法是broadcast join,即将join左边的表分割到多个worker,然后将join右边的表数据整个复制一份发送到每个worker进行计算。如果右边的表数据量太大,则可能会报内存溢出错误。
[GOOD] SELECT ... FROM large_table l join small_table s on l.id = s.id
[BAD] SELECT ... FROM small_table s join large_table l on l.id = s.id
- 使用Rank函数代替row_number函数来获取Top N
在进行一些分组排序场景时,使用rank函数性能更好
[GOOD]
SELECT checksum(rnk)
FROM (
SELECT rank() OVER (PARTITION BY l_orderkey, l_partkey ORDER BY l_shipdate DESC) AS rnk
FROM lineitem
) t
WHERE rnk = 1
[BAD]
SELECT checksum(rnk)
FROM (
SELECT row_number() OVER (PARTITION BY l_orderkey, l_partkey ORDER BY l_shipdate DESC) AS rnk
FROM lineitem
) t
WHERE rnk = 1
字符串函数
下表列出了String函数。
序号 | 功能与说明 |
---|---|
1 | concat(string1,...,stringN) 连接给定的字符串 |
2 | length(string) 返回给定字符串的长度 |
3 | lower(string) 返回字符串的小写格式 |
4 | upper(string) 返回给定字符串的大写格式 |
5 | lpad(string,size,padstring) 给定字符串的左填充 |
6 | ltrim(string) 从字符串中删除前导空格 |
7 | replace(string, search, replace) 替换字符串值 |
8 | reverse(string) 反转对字符串执行的操作 |
9 | rpad(string,size,padstring) 给定字符串的正确填充 |
10 | rtrim(string) 从字符串中删除尾随的空格 |
11 | split(string, delimiter) 拆分分隔符上的字符串,并返回最大限制的大小数组 |
12 | split_part(string, delimiter, index) 拆分分隔符上的字符串并返回字段索引 |
13 | strpos(string,substring) 返回字符串中子字符串的起始位置 |
14 | substr(string,start) 返回给定字符串的子字符串 |
15 | substr(string,start,length) 返回具有特定长度的给定字符串的子字符串 |
16 | trim(string) 从字符串中删除前导和尾随空格 |
来源:oschina
链接:https://my.oschina.net/u/3071470/blog/3005324