Amazon Athena 性能调整

1.分割你的数据

  • 分区将表分成几部分,并根据列值(如日期,国家,地区等)将相关数据保存在一起。分区作为虚拟列。您可以在表创建时定义它们,并且可以帮助减少每个查询扫描的数据量,从而提高性能。您可以通过基于分区指定过滤器来限制查询扫描的数据量。有关更多详细信息,请参阅分区数据。
  • 您可以使用“WHERE”子句中的列来限制查询中扫描的分区。
SELECT id, userName FROM user WHERE age = 20
SELECT count(*)FROM user WHERE age > =20 AND age < 25

2.压缩和分割文件

  • 压缩数据可以显着加快查询速度,只要文件是最佳大小(参见下一节)或文件是可拆分的。较小的数据大小可将网络流量从S3降低到雅典娜。

  • 可分解文件允许雅典娜的执行引擎将多个读者的文件读取分割,以增加并行性。如果您有一个不可分解的文件,则只有一个读卡器才能读取该文件,而所有其他读卡器都闲置。并不是所有的压缩算法都是可分割的。下表列出了常见的压缩格式及其属性。

  • 通常,算法的压缩比越高,压缩和解压缩数据所需的CPU越多。

  • 对于雅典娜,我们建议使用Apache Parquet或Apache ORC,它默认压缩数据并且是可拆分的。当它们不是一个选项时,尝试使用最佳文件大小的BZip2或Gzip。

3.优化文件大小

  • 当读取数据可以并行化并且可以顺序读取数据块时,查询运行效率更高。确保您的文件格式是可分割的,有助于并行化,无论文件大小多大。

  • 但是,如果您的文件太小,通常少于128 MB,则执行引擎可能会花费额外的时间来开启S3文件,列出目录,获取对象元数据,设置数据传输,阅读文件头,阅读压缩字典等等。另一方面,如果您的文件不可分割,并且文件太大,则查询处理将等待直到单个读取器完成读取整个文件。这可以减少并行性。

  • 解决您的小文件问题的一个补救办法是在EMR上使用S3DistCP实用程序。您可以将较小的文件组合成较大的对象。S3DistCP还可用于将大量数据从HDFS移动到S3,S3到S3,S3到HDFS

4.优化ORDER BY

  • ORDER BY子句按排序顺序返回查询的结果。为了进行排序,Presto必须将所有行数据发送给单个工作人员,然后对其进行排序。这可能会导致Presto的内存压力,这可能导致查询花费很长时间才能执行。更糟糕的是,查询可能会失败。

  • 如果您正在使用ORDER BY子句来查看顶部或底部的N值,那么使用LIMIT子句可以通过将排序和限制推送给单个工作人员来显着减少排序成本,而不是单个排序工人。

SELECT * FROM user ORDER BY age   //426
SELECT * FROM user ORDER BY age LIMIT 10000  //12.59

5.优化连接

  • 当您连接两个表时,请在连接的左侧指定较大的表,并在连接的右侧指定较小的表。Presto将表右边的表分发给工作节点,然后在左侧发送表以进行连接。如果右侧的表格较小,则使用的内存较少,查询运行速度更快。
SELECT count(*)FROM lineitem,part WHERE lineitem.l_partkey = part.p_partkey  //12.5s
SELECT count(*)FROM part,lineitem WHERE lineitem.l_partkey = part.p_partkey  //11s
  • 规则的例外是将多个表连接在一起,并且可能存在交叉连接。Presto将从左到右执行连接,因为它不支持连接重新排序。因此,您应该指定从最大到最小的表,同时确保两个表不一起指定,这将导致交叉连接。

询问  运行
SELECT count(*)FROM lineitem,customer,orders WHERE lineitem.l_orderkey = orders.o_orderkey AND customer.c_custkey = orders.o_custkey //连接超时
SELECT count(*)FROM lineitem,orders,customer WHERE lineitem.l_orderkey = orders.o_orderkey AND customer.c_custkey = orders.o_custkey    //3s

6.优化group by

  • GROUP BY运算符将GROUP BY列分配给工作节点,该节点将GROUP BY值保存在内存中。随着行被捕获,GROUP BY列将在内存中查找,并对值进行比较。如果GROUP BY列匹配,则将这些值聚合在一起。

  • 在查询中使用GROUP BY时,按列的顺序排列最高基数(即大多数唯一值均匀分布)的列为最低。

SELECT state, gender, count(*) 
           FROM census 
GROUP BY state, gender;
  • 另一个优化是在GROUP BY子句中使用数字而不是字符串,如果可能的话。数字需要更少的内存来存储,并且比字符串更快地进行比较。

  • 另一个优化是限制SELECT语句中的列数,以减少存储在内存中所需的内存量,因为行保存在内存中并为GROUP BY子句聚合。

7.优化LIKE操作符

  • 当您对字符串列中的多个值进行过滤时,通常最好多次使用RegEx而不是LIKE。更多的原因和更大的字符串列,使用RegEx将节省更多。
SELECT count(*)FROM lineitem WHERE l_comment LIKE'%wake%'OR l_comment LIKE'%regular%'OR l_comment LIKE'%express%'OR l_comment LIKE'%sleep%'OR l_comment LIKE'%hello%     //25s
SELECT count(*)FROM lineitem WHERE regexp_like(l_comment,'wake | regular | express | sleep | hello')   //15s

8.使用近似功能

  • 为了探索大型数据集,常见的用例是使用COUNT(DISTINCT列)查找特定列的不同值的计数。一个例子是查看访问网页的唯一身份用户的数量。

  • 当一个确切的数字可能不需要 - 例如,如果您正在寻找哪些网页深入潜水,请考虑使用近似的()。此函数尝试通过计算值的唯一哈希值而不是整个字符串来最小化内存使用。缺点是标准错误为2.3%。

SELECT countdistinct l_comment) FROM lineitem; //13s
SELECT about_distinct(l_comment) FROM lineitem;//11s
  • 只包括你需要的列
    • 运行查询时,将最终的SELECT语句限制为仅需要的列,而不是选择所有列。修剪列数减少了整个查询执行管道需要处理的数据量。当查询具有大量列和基于字符串的列的表时,这尤其有用。
SELECT * FROM lineitem,orders,customer WHERE lineitem.l_orderkey = orders.o_orderkey AND customer.c_custkey = orders.o_custkey;   //980s
SELECT customer.c_name,lineitem.l_quantity,orders.o_totalprice FROM lineitem,orders,customer WHERE lineitem.l_orderkey = orders.o_orderkey AND customer.c_custkey = orders.o_custkey;  //15s

注:原文地址:https://aws.amazon.com/cn/blogs/big-data/top-10-performance-tuning-tips-for-amazon-athena/

猜你喜欢

转载自blog.csdn.net/m0_37204491/article/details/74719557
今日推荐