当前位置: 首页 > Linux

Presto上使用SQL遇到的一些坑

时间:2023-04-06 22:38:53 Linux

最近换了一份新工作。在数据处理方面,公司使用Presto连接各业务部门的数据库,直接使用SQL进行数据处理。曾经不是很合适。经过一段时间的工作,有了一些感触,决定把遇到的一些坑记录下来。什么是急板?有什么好处?从官方文档中,我们了解到Presto是一个分布式SQL查询引擎,用于查询分布在一个或多个不同数据源中的大数据集。不要以为Presto可以解析SQL,那么Presto就是一个标准的数据库。Presto被设计为数据仓库和数据分析产品:数据分析、大规模数据聚合和报表生成。这些工作通常被认为是在线分析处理操作。因此,当公司业务有跨库分析时(一般业务数据库分布在各个部门),需要将部分数据与其他部门的数据进行关联查询。这时候可以考虑Presto。但是目前,MySQL统计查询的性能存在瓶颈。考虑按时间段将数据归档到HDFS,提高统计效率。如果需要实时统计业务数据库,不需要跨库操作,建议直接连接数据库。遇到的问题如何加快Presto上的数据统计当Presto上有大量的数据统计时,跨库查询到Presto上的数据库,比如Mysql数据库。这时候Presto的做法是从MySQL数据库拉取最基础的数据,然后做进一步的处理,比如统计等聚合操作。举个栗子:SELECTcount(id)FROMtable_1WHEREcondition=1;上面的SQL语句将分为3步:Presto向Mysql数据库发起查询SELECTidFROMtable_1WHEREcondition=1;计算结果并返回结果,对于Presto来说,其跨库查询的瓶颈在于数据拉取这一步。为了提高数据统计的速度,可以考虑定期将Mysql中的相关数据表转移到HDFS,再转移到ORC这种高效的列式存储格式。因此,定期归档是一个不错的选择。这里注意,在归档的时候,我们需要选择一个归档字段。如果按天归档,我们可以使用日期作为该字段的值,格式为yyyyMMdd,如20180123。一般创建归档数据库的SQL语句如下:CREATETABLEIFNOTEXISTStable_1(idINTEGER,.....partition_dateINTEGER)WITH(format='ORC',partitioned_by=ARRAY['partition_date']);查看创建库结构:SHOWCREATETABLEtable_1;/*OnlyPresto*/创建带分区的表后,只需要每天更新分区字段partition_date,智能的Presto就可以将数据放到规划的分区中。如果要查看数据表的分区字段是什么,可以使用如下语句:SHOWPARTITIONSFROMtable_1/*OnlyPresto*/尝试在查询条件中带上分区字段来过滤数据是否存储在HDFS并具有分区字段。每次查询归档表时,都需要带上分区字段作为过滤条件,这样可以加快查询速度。因为使用分区字段作为查询条件,可以帮助Presto避免全区扫描,减少Presto需要扫描的HDFS文件数量。在用Presto使用WITH语句分析统计数据时,可以考虑将多个查询合并为一个查询,使用Presto提供的子查询来完成。这和我们熟悉的MySQL的使用不太一样。例如:WITHsubquery_1AS(SELECTa1,a2,a3FROMTable_1WHEREa3between20180101and20180131),/*子查询subquery_1,注意:多个子查询需要用逗号隔开*/subquery_2AS(SELECTb1,b2,b3FROMtable_2WHEREb3between20180101and20180131)/*最后一个子查询后面不要加逗号,否则会报错。*/SELECTsubquery_1.a1,subquery_1.a2,subquery_2.b1,subquery_2.b2FROMsubquery_1JOINsubquery_2ONsubquery_1.a3=subquery_2.b3;使用子查询减少表的读取次数,尤其是对于数据量大的表,将经常使用的表提取为子查询,以避免多次读取。要只查询必填字段,必须避免在查询中使用SELECT*等语句。换个角度想,如果让你去查询数据,是不是告诉你数据越具体,工作效率就越高?我们的数据库也是如此,任务越具体,工作效率就越高。需要查询所有字段也是一样,偷懒没有捷径,全部写出来。加入查询优化。尽量将小数据表放在Join的左侧,最好引用表字段名,关联键重复次数少。Presto中的字段名引用是用双引号分隔的,这与MySQL的反引号`.当然,您可以省略双引号。当时间函数需要比较时间戳时,需要加上timestamp关键字,MySQL可以直接比较时间戳。/*MySQL*/SELECTtFROMaWHEREt>'2017-01-0100:00:00';/*Presto*/SELECTtFROMaWHEREt>timestamp'2017-01-0100:00:00';使用MD5函数Presto中的MD5函数传入二进制类型,返回二进制类型。对字符串进行MD5运算时,需要进行转换。选择to_hex(md5(to_utf8('1212')));不支持INSERTOVERWRITE语法Presto不支持insertoverwrite语法,只能先delete,再insertinto。ORC格式Presto中对ORC文件格式进行了优化,但目前Impala中不支持ORC格式的表,hive中支持ORC格式的表,所以在使用列式存储时可以优先使用ORC格式。PARQUET格式Presto目前支持parquet格式,支持query,但不支持insert。