spark3.3版本功能增强细项

spark3.3版本功能增强细项

         Apache Spark 3.3. 是 3.x 系列的第四个版本,此版本更好的错误处理、自动完成、性能和分析提高了开发效率。为此整理了一份更改列表,便于熟悉了解新增算子及优化后功能的使用方式。

1.支持 ANSI SQL INTERVAL 类型(SPARK-27790

应用场景:

•   数据分析和报告:在需要精确计算和展示时间间隔(如平均延误时间、平均处理时间等)的数据分析项目中。

•   时间序列数据处理:处理时间序列数据时,经常需要计算时间间隔,比如金融领域的利率计算

•   在系统性能监控中,需要准确跟踪和报告各种操作的持续时间

在 Spark SQL 中,时间间隔可以通过 INTERVAL 关键字来直接表示,它可以与其他的日期和时间类型相结合进行计算,比如添加到一个日期或者时间戳上。这里举一个简单的例子

  1. // 示例: 使用 Spark SQL  interval 来表示时间间隔,并计算一个月后的日期
  2. val dateDF = Seq("2023-01-01").toDF("startDate")
  3. // 将字符串转换为日期格式
  4. val startDateDF = dateDF.selectExpr("to_date(startDate) as startDate")
  5. // 计算一个月后的日期
  6. startDateDF.createOrReplaceTempView("dateTable")
  7. val intervalDF = spark.sql("SELECT startDate, startDate + INTERVAL 1 MONTH as plusOneMonth FROM dateTable")
  8. intervalDF.show()

2.支持原始字符串文字(SPARK-36371

SPARK-36371特性通过支持原始字符串字面量,简化了在编写Spark SQL时处理需要转义字符的字符串的复杂度,特别是对于那些复杂的正则表达式和JSON字符串的操作,这使得代码更加直观和容易维护。

3.允许在日期时间类型之间存储分配和隐式转换(SPARK-37707

SPARK-37707是Apache Spark项目中的一个改进,其主要特性是允许在TimestampNTZ(不带时区的时间戳类型)和Date/Timestamp(日期/带时区的时间戳类型)之间进行存储分配和隐式转换。在Spark 3.3.0版本中引入,这项改进提高了Spark在处理日期和时间类型数据时的灵活性和效率。

使用案例和使用场景

场景一:统一时间戳格式

在处理来自不同数据源的时间戳数据时,数据中可能既有带时区的时间戳(Timestamp),也有不带时区的时间戳(TimestampNTZ)。SPARK-37707的特性可以在这些不同类型的时间戳数据之间进行转换,从而使数据分析和处理更加灵活。

例如,如果你的数据库中存储的是不带时区的时间戳(TimestampNTZ),而你的应用程序期望使用带时区的时间戳进行处理,你可以利用这项特性进行转换,而无需编写额外的转换代码:

  1. // 假设df为含有不带时区的时间戳列的DataFrame  
  2. import org.apache.spark.sql.functions._  
  3.   
  4. val convertedDf = df.withColumn("timestamp_with_tz", col("timestamp_ntz_column").cast("timestamp")) 

场景二:灵活处理日期和时间数据

在进行数据清洗和预处理时,有时需要将日期类型的数据转换为时间戳类型,或者相反。这项特性简化了这种转换操作,使开发者可以根据实际情况灵活选择使用哪种类型,优化数据处理流程。

例如,你可能需要将不带时区的时间戳(TimestampNTZ)转换为日期类型(Date),以便按日期进行数据汇总:

  1. // 假设df为含有不带时区的时间戳列的DataFrame  
  2. val dateDf = df  
  3.   .withColumn("date", col("timestamp_ntz_column").cast("date"))  

4.Collect、first 和 last 应该是确定性的聚合函数 ( SPARK-32940 )

SPARK-32940是Apache Spark的一个改进提案,解决了collect, first 和 last 这三个聚合函数在使用时可能产生的非确定性问题。在Spark之前的版本中,当对一个分组使用这些函数时,如果分组内的元素顺序是不确定的,那么这些聚合函数的结果也可能是不确定的。为了解决这个问题,SPARK-32940提出将这些函数变为确定性的聚合函数,使得在相同的输入和相同的环境设置下,它们总能返回相同的结果.

5.添加按名称联合的数组支持 ( SPARK-36546 )

SPARK-36546 是 Apache Spark 3.3.0 版本中引入的一个特性,旨在改进unionByName方法处理结构体数组(array of struct columns)时的空值填充(null-filling)行为。在这个改进之前,当使用unionByName对包含结构体数组的数据集合并时,如果两个数据集的某个结构体数组列在部分行上存在字段不一致的情况,那么这些不一致的字段将不会被自动处理。SPARK-36546 的引入,使得在这种情况下,缺失的字段会被自动用null值填充,保证了数据集合并的完整性和一致性。

使用案例和使用场景

场景一:整合不同数据源的数据

  1. // 假设df1和df2是两个来源于不同供应商的DataFrame,它们含有商品信息,包括一个结构体数组列"attributes"  
  2. // df1的"attributes"包含(品牌,尺寸,颜色),而df2的"attributes"可能只包含(品牌,颜色)  
  3.   
  4. val integratedDF = df1.unionByName(df2, true) // 使用true参数开启空值填充行为

场景二:历史数据与新数据的整合

对于一个长期运行的数据处理系统,随着时间的推移,数据的结构可能发生变化。例如,可能新增了某些字段。在整合旧数据(缺少新字段)和新数据(包含新字段)时,可以利用SPARK-36546提供的功能确保数据集在合并后字段完整,新字段在旧数据中将被以null填充。

  1. // 假设oldDF是包含旧数据结构的DataFrame,newDF是包含新数据结构(比如,多了一个字段"new_field")的DataFrame  
  2.   
  3. val combinedDF = oldDF.unionByName(newDF, true) // 新字段在oldDF中的对应行将被填充为null  

6.使用 CAST 以默认模式解析日期/时间戳(SPARK-36418

SPARK-36418是针对Apache Spark SQL中日期和时间戳默认格式解析的一个改进,该问题已经在Apache Spark的3.3版本中得到解决。这个改进使得在默认情况下,日期和时间戳字段的解析更加健壮。

场景:SQL查询中转换日期和时间戳格式

假设你正在处理一个包含多种日期和时间字符串格式的表格,你想将所有日期和时间都转换为标准格式,以确保后续操作的一致性。

在SPARK-36418之前,如果你尝试像下面这样使用CAST将字符串转换为日期或时间戳,转换可能会失败。

  1. SELECT CAST('2022-03-15' AS DATE) AS date;  
  2. SELECT CAST('2022-03-15 13:24:56' AS TIMESTAMP) AS timestamp;  

而有了SPARK-36418的改进,Spark SQL的这些CAST操作变得更加健壮,不会因为格式的细微差别而失败。

  1. -- 假设有一个表 `events`,包含一列名为 `event_time` 的时间戳字符串  
  2.   
  3. -- 设置Spark SQL的环境变量,指定默认的时间戳格式  
  4. SET spark.sql.session.timeZone = UTC;  
  5. SET spark.sql.legacy.timeParserPolicy = LEGACY;  
  6.   
  7. -- 改善后,你可以在SQL查询中像下面这样转换时间戳  
  8. SELECT event_name,  
  9.        CAST(event_time AS TIMESTAMP) AS timestamp  
  10. FROM events;  

7.添加 AS OF 语法支持(SPARK-37219

Delta Lake 时间旅行允许用户查询 Delta 表的旧快照。要查询表的旧版本,用户需要在 SELECT 语句中使用 AS OF 语法指定版本或时间戳.

场景:数据的时间点比较:

  1. -- 假设已知月初的版本号为5,月末的版本号为10  
  2. -- 查询月初数据  
  3. WITH start_of_month AS (  
  4.   SELECT *  
  5.   FROM sales_data AS OF 5  
  6. )  
  7. -- 查询月末数据  
  8. , end_of_month AS (  
  9.   SELECT *  
  10.   FROM sales_data AS OF 10  
  11. )  
  12. -- 进行比较分析  
  13. SELECT *  
  14. FROM start_of_month  
  15. FULL OUTER JOIN end_of_month  
  16. ON start_of_month.sale_id = end_of_month.sale_id  
  17. WHERE start_of_month.amount != end_of_month.amount OR (start_of_month.amount IS NULL OR end_of_month.amount IS NULL);  

8.在 TABLESAMPLE 中添加 REPEATABLE 来指定种子(SPARK-37165

SPARK-37165 是 Apache Spark 的一个改进特性,它允许在使用TABLESAMPLE语句进行数据抽样时添加REPEATABLE关键字来指定种子值。这个特性的引入使得数据抽样结果可以变得可重复,即使用同一个种子值进行抽样时,无论执行多少次,得到的样本集合都是一样的。这对于数据分析、测试或者模型训练等需要可重复的数据抽样结果的场景非常有用。

示例:使用TABLESAMPLE进行可重复的数据抽样

考虑以下场景,你有一个包含网站交易数据的大表transactions,现在需要抽取其中的一部分数据来进行分析。使用TABLESAMPLE结合REPEATABLE可以如下进行:

  1. -- 假设想要随机抽取表中约10%的数据进行分析,且希望结果是可重复的  
  2. SELECT *  
  3. FROM transactions TABLESAMPLE (10 PERCENT) REPEATABLE (123); 

在这个SQL语句中,TABLESAMPLE (10 PERCENT)表示从transactions表中随机抽取大约10%的行。REPEATABLE (123)指定了种子值123,这意味着只要种子值不变,无论这个查询执行多少次,抽样得到的行集合都会是相同的。

9.支持查询阶段以格式化解释模式显示运行时统计信息(SPARK-38322

SPARK-38322是Apache Spark项目中的一个改进项,其目标是在格式化解释模式(formatted explain mode)中支持查询阶段显示运行时统计信息。这项功能的增加对于深入理解和优化Spark SQL查询性能具有重要价值,因为它使得开发者能够更直观地看到各个查询阶段的详细运行时统计信息,从而更容易识别性能瓶颈。

示例案例

使用以下SQL查询来分析用户的行为数据,查询目的是找出前10名在某个特定时间段内活动最频繁的用户。

  1. SELECT user_id, COUNT(*) AS activity_count  
  2. FROM user_activities  
  3. WHERE timestamp BETWEEN '2023-01-01' AND '2023-01-31'  
  4. GROUP BY user_id  
  5. ORDER BY activity_count DESC  
  6. LIMIT 10; 

为了优化这个查询,分析师想要查看其执行计划以及运行时统计信息。引入SPARK-38322后,可以使用新的格式化解释模式来实现这一点:

  1. EXPLAIN FORMATTED SELECT user_id, COUNT(*) AS activity_count  
  2. FROM user_activities  
  3. WHERE timestamp BETWEEN '2023-01-01' AND '2023-01-31'  
  4. GROUP BY user_id  
  5. ORDER BY activity_count DESC  
  6. LIMIT 10;  

执行上述命令后,Spark将提供一个详细的执行计划,其中包括每个查询阶段的运行时统计信息,如耗时、处理的数据量等。这使得开发者可以更容易地识别查询性能的瓶颈并进行相应的优化。

10.为排序合并连接添加溢出大小指标 ( SPARK-37726 )

SPARK-37726是Apache Spark项目中的一个改进项,它增加了对于sort merge join操作的“溢出大小”(spill size)SQL指标,能够指示在执行阶段有多少数据被溢写到磁盘。在做sort merge join时,如果参与join的一侧数据太大而无法全部加载到内存,Spark会将部分数据溢写到磁盘中,以减少内存使用并避免OutOfMemory错误。通过这个指标,用户可以更清楚地了解join操作中数据溢写的行为,以及它对性能的可能影响,尤其是在处理大规模数据集时。

示例案例

为了合并用户点击流数据和订单数据,分析师可能会使用sort merge join来合并两者:

  1. SELECT clicks.user_id, clicks.session_id, orders.order_id, orders.amount  
  2. FROM user_clicks clicks  
  3. JOIN user_orders orders  
  4. ON clicks.user_id = orders.user_id  
  5. AND clicks.timestamp <= orders.timestamp 

这里假设user_clicks与user_orders是两个较大的数据集,并且已被决定通过用户ID来关联。但在执行上述join操作时,如果内存不足以容纳这些数据,Spark需要将部分数据溢出到磁盘,这将可能影响到查询性能。

通过SPARK-37726引入的溢出大小指标,执行SQL时将收集关于溢出数据大小的度量信息。理解查询性能表现及其背后的原因。

  1. EXPLAIN COST SELECT clicks.user_id, clicks.session_id, orders.order_id, orders.amount  
  2. FROM user_clicks clicks  
  3. JOIN user_orders orders  
  4. ON clicks.user_id = orders.user_id  
  5. AND clicks.timestamp <= orders.timestamp  

11.添加TIMESTAMPADD () 函数(SPARK-38195

SPARK-38195与在Apache Spark SQL中添加TIMESTAMPADD()函数有关。TIMESTAMPADD()函数是ODBC API的一部分,并且几乎被所有其他数据库实现。在Spark SQL中,这个函数似乎在之前的版本中并未实现。

为了给你一个使用场景和實例,假设在数据库中有一个包含订单和订单日期的表orders且有一个order_date时间戳列。你想要找出三个月之后的时间戳。使用TIMESTAMPADD()函数

  1. SELECT order_id, TIMESTAMPADD(MONTH, 3, order_date) AS new_date   
  2. FROM orders;  

添加TIMESTAMPDIFF () 函数 ( SPARK-38284 )

TIMESTAMPDIFF() 函数也非常方便,并且是一个很好的补充, spark 中获取两个时间戳之间的秒差需要转换为 unixtimestamp 并转回。

选择TIMESTAMPDIFFSECOND'2021-12-30 01:02:00'时间戳,   '2021-12-30 01:00:00'时间戳

>120

--当前支持

SELECT unix_timestamp( '2021-12-30 01:00:00' :时间戳) - unix_timestamp( '2021-12-30 01:00:00' :时间戳)

> 120

12.添加convert_timezone () 函数(SPARK-37552SPARK-37568

使用场景

假设我们有一个国际销售数据表sales,各条记录有一个时间戳字段sale_time(记录了销售发生的时间,并采用UTC时区)。但在报告这些销售数据时,我们需要将它们转换至纽约时区(东部时间)。

SQL使用方式

在Spark SQL中,使用convert_timezone()函数的查询可以是这样的:

  1. SELECT sale_id,  
  2.        sale_time,  
  3.        convert_timezone('UTC', 'America/New_York', sale_time) AS sale_time_ny  
  4. FROM sales;  

13.添加aes_encryptaes_decrypt内置函数 ( SPARK-12567 )通过aes_encrypt ()/ aes_decrypt

SPARK-12567提出了在Apache Spark中添加aes_encrypt和aes_decrypt这两个用户定义函数(UDF),这两个函数基于高级加密标准(AES)算法来实现数据的加密和解密。这对于需要处理敏感信息(如个人身份信息、信用卡号码等)的数据处理场景十分有用,因为它允许数据在存储和传输过程中保持加密状态,从而提高数据的安全性。

添加aes_encrypt和aes_decrypt内置函数 ( SPARK-12567 )通过aes_encrypt ()/ aes_decrypt.。

加密:

  1. SELECT user_id,  
  2.        aes_encrypt('my_secret_key', credit_card_info) AS encrypted_info  
  3. FROM user_payments;  

解密:

  1. SELECT user_id,  
  2.        aes_decrypt('my_secret_key', encrypted_info) AS decrypted_info  
  3. FROM user_payments;  

14.支持 GCM 模式( SPARK-37591 )

SPARK-37591 关注于为 aes_encrypt() 和 aes_decrypt() 用户定义函数(UDF)添加对Galois/Counter Mode(GCM)模式的支持。GCM是一种加密模式,提供了同时加密数据和对数据的完整性和真实性提供保护的能力。这一改进使得Apache Spark能够更加安全有效地处理加密数据,特别是在需要验证数据未被篡改的场景中。

SQL使用方式

加密数据并验证数据完整性:

  1. SELECT payment_id,  
  2.        aes_encrypt('my_secret_key', payment_details, 'GCM') AS encrypted_details  
  3. FROM payments;  
  4. 在此示例中,aes_encrypt函数接收三个参数:一个用于加密的秘钥('my_secret_key'),待加密的数据(payment_details),以及加密模式('GCM')。这条SQL语句产生了每笔支付的ID和对应的加密支付细节,同时加密操作包括了对数据完整性的保护。

解密数据并验证数据完整性:

  1. SELECT payment_id,  
  2.        aes_decrypt('my_secret_key', encrypted_details, 'GCM') AS decrypted_details  
  3. FROM payments;  

这里,aes_decrypt同样接收三个参数:加密时使用的秘钥('my_secret_key'),加密后的数据(encrypted_details),以及加密模式('GCM')。这条SQL语句返回每笔支付的ID和解密后的支付细节,同时在解密过程中验证了数据的完整性与真实性。

15.添加密码模式选项,并为 aes_encrypt 和 aes_decrypt 设置默认密码模式

SPARK-37586 主要关于为 aes_encrypt 和 aes_decrypt 函数添加了一个密码模式选项,并为这两个函数设置了默认的密码模式。这项改进使得用户在使用这两个函数进行数据加密和解密时可以指定密码模式,从而增加了灵活性和安全性。默认的密码模式的设置帮助简化了函数的使用,同时也保证了良好的安全性。

SQL使用方式

加密账户信息

考虑到数据加密的需求,你可以使用aes_encrypt函数对account_info列的数据进行加密,如下所示:

  1. SELECT name,  
  2.        aes_encrypt('my_secret_key', account_info, 'CFB') AS encrypted_account_info  
  3. FROM customer_info;  

解密账户信息

为了在需要时获取原始的账户信息,可以使用aes_decrypt函数对数据进行解密:

  1. SELECT name,  
  2.        aes_decrypt('my_secret_key', encrypted_account_info, 'CFB') AS decrypted_account_info  
  3. FROM encrypted_customer_info;  

通过在aes_encrypt和aes_decrypt函数中指定加密模式,银行的数据处理系统能够以符合安全标准的方式保护客户的敏感信息。SPARK-37586所引入的改进不仅提高了数据处理的安全性,同时通过设置默认的密码模式,也简化了这两个函数的使用,为用户提供了更好的灵活性和便利性。

16.支持 ANSI 聚合函数:regr_countSPARK-37613

SPARK-37613是针对Apache Spark中增加ANSI SQL标准聚合函数regr_count的支持。regr_count是一种统计函数,用于计算回归分析中非空数值对的数量。该功能对于执行回归分析,特别是在处理大量数据时非常有用,因为它提供了一种高效、标准化的方法来分析数据集中的变量之间的线性关系。

SQL使用方式

假定有一个表sales_data,包含了每一笔销售的产品价格(price)和销售数量(quantity)。

计算价格和数量之间非空数值对的数量:

  1. SELECT regr_count(price, quantity) AS non_null_pairs_count  
  2. FROM sales_data;  

在这个例子中,regr_count函数接收两个参数:第一个参数是自变量(在这个例子中是price),第二个参数是因变量(在这个例子中是quantity)。regr_count函数将返回数据集中价格和数量之间非空数值对的数量。这个结果有助于确定数据集的完整性和适用性.

17.支持 ANSI 聚合函数:regr_avgx和regr_avgy ( SPARK-37614 )

SPARK-37614 是关于在Apache Spark中增加支持两个 ANSI SQL 标准聚合函数:regr_avgx 和 regr_avgy。这两个函数用于回归分析,分别计算自变量的平均值和因变量的平均值。在处理包含多个数据点的数据集时,regr_avgx 和 regr_avgy 对于快速获取分析所需的均值信息非常有用,特别是在进行线性回归分析或其他统计分析时。

SQL使用方式

计算广告支出的平均值(regr_avgx)和月销售额的平均值(regr_avgy):

假设数据存储在名为 company_sales 的表中,包含列 ad_spend 和 monthly_sales。

  1. SELECT  
  2.     regr_avgx(ad_spend, monthly_sales) AS avg_ad_spend,  
  3.     regr_avgy(ad_spend, monthly_sales) AS avg_monthly_sales  
  4. FROM  
  5.     company_sales;  

在这个SQL语句中,regr_avgx 函数和 regr_avgy 函数分别计算广告支出和月销售额的平均值。这两个函数各自接收两个参数:regr_avgx 的第一个参数是自变量(ad_spend),第二个参数是因变量(monthly_sales);同理,regr_avgy 的第一个参数同样是自变量(ad_spend),第二个参数是因变量(monthly_sales)。

18.支持 ANSI 聚合函数:regr_r2 ( SPARK-37641 )

SPARK-37641是关于Apache Spark新增对ANSI SQL标准聚合函数regr_r2的支持。regr_r2函数用于计算线性回归分析中的决定系数(R^2),它是衡量模型拟合优度的一个重要指标。简而言之,决定系数说明了自变量对因变量的变异度的解释程度。其值范围从0到1,值越接近1意味着自变量对因变量的解释度越高。

使用场景

假设一个房地产公司希望分析房屋面积(square_feet)和房屋售价(price)之间的关系。通过计算决定系数,公司能够了解房屋面积在多大程度上能够决定房屋的售价。这种分析可以帮助公司更好地为客户估价,以及制定相关的市场策略。

SQL使用方式

假设存在一个名为house_sales的表,其中包含列square_feet(自变量)和price(因变量)。

计算房屋面积对房屋售价的决定系数(R^2):

  1. SELECT regr_r2(square_feet, price) AS determination_coefficient  
  2. FROM house_sales;  

在这个例子中,regr_r2函数接收两个参数:第一个参数是自变量square_feet,第二个参数是因变量price。该函数会返回决定系数,即在给定数据集上自变量如何解释因变量的变化。

SPARK-27974是关于在Apache Spark中新增支持ANSI SQL标准聚合函数array_agg。这个聚合函数可以将一组值聚合成一个数组。相较于其他聚合函数,如SUM或AVG,array_agg提供了一种灵活的方式来处理集合数据,使其能够在分析复杂数据结构时发挥强大的作用。

19.支持 ANSI 聚合函数:percentile_contSPARK-37676SPARK-38219

SPARK-37676是关于Apache Spark中新增对ANSI SQL标准聚合函数PERCENTILE_CONT的支持。PERCENTILE_CONT是一种非常有用的统计函数,它用于计算给定百分位数在数据集中的连续值.

SQL使用方式

以下SQL查询演示了如何使用PERCENTILE_CONT函数来计算订单金额的中位数:

这个查询将会计算orders表中所有订单金额的中位数,并给出一个名为median_order_amount的结果。这里0.5参数表示50%百分位数,代表中位数。WITHIN GROUP (ORDER BY amount)子句是必需的,它指定了PERCENTILE_CONT函数应该如何对数据排序以计算百分位数。

SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median_order_amount

FROM orders;

20.支持 ANSI 聚合函数:percentile_disc ( SPARK-37691 )

PERCENTILE_DISC是一个SQL中的统计函数,它用来计算离散的百分比值。在某个数据集中,PERCENTILE_DISC函数用于确定在指定的百分比点上或之前的最高值。这意味着,该函数返回的是原始数据集中存在的确切值,而非像PERCENTILE_CONT所做的那样通过插值计算出来的连续值。

使用方式:

PERCENTILE_DISC函数通常与WITHIN GROUP (ORDER BY ...)结合使用,这样可以指定计算百分位数时数据的排序方式。以下是一个使用PERCENTILE_DISC函数的基本语法结构:

PERCENTILE_DISC(百分比) WITHIN GROUP (ORDER BY 排序的列) OVER (分区字句)

这里的:

百分比是一个介于0和1之间的小数,代表希望计算的百分位数。

排序的列是指定计算百分位数时应如何对数据进行排序。

分区子句是可选的,它允许在进行百分位数计算时对数据进行分区。

使用场景:

假设你有一个名为student_scores的表,里面包含了两个列:student_id和score,现在你想要找到班级成绩中位于前30%最高分的分数(即30%的百分位点),那么可以这样写:

这条查询会返回student_scores中score列在排序后位于前30%位置的最高成绩。

SELECT PERCENTILE_DISC(0.3) WITHIN GROUP (ORDER BY score)

FROM student_scores;

21.引入 SQL 函数ARRAY_SIZE ( SPARK-38345 )

计算数组中元素的个数:

SELECT user_id, actions,

       ARRAY_SIZE(actions) AS action_count

FROM user_actions

WHERE ARRAY_SIZE(actions) > 10;

22.新的 SQL 函数:map_contains_key ( SPARK-37584 )

添加新函数 map_contains_key,如果 map 包含 key,则返回 true

例子:

> SELECT map_contains_key(map(1,'a',2,'b'), 1);
true
> SELECT map_contains_key(map(1,'a',2,'b'), 3);
false

23.新的 SQL 函数:try_element_atSPARK-37533

添加新的 SQL 函数 `try_element_at`,它与 `element_at` 相同,只是如果发生错误则返回 null

24.新的 SQL 函数:try_sum ( SPARK-38548 )

添加新的 SQL 函数:try_sum。它与函数完全相同sum,只是它返回NULL结果,而不是在整数/小数值溢出时抛出异常。
注意,当 ANSI 模式关闭时,它与 sum 不同:

功能

尝试求和

十进制溢出

返回 NULL

返回 NULL

整数溢出

返回结果的低64位

返回 NULL

为什么需要这些改变?

  • 用户可以在 ANSI 模式下不间断地完成查询。
  • 如果在 ANSI 模式关闭时发生溢出,用户可能会得到 NULL,而不是不合理的结果。例如
> SELECT sum(col) FROM VALUES (9223372036854775807L), (1L) AS tab(col);
-9223372036854775808
 
> SELECT try_sum(col) FROM VALUES (9223372036854775807L), (1L) AS tab(col);
NULL

25.添加新的 SQL 函数to_binarySPARK-37507SPARK-38796

引入 SQL 函数to_binary:根据提供的格式(如何解释字符串)将输入字符串转换为二进制值。

句法:

to_binary(str_column[, fmt])

在哪里

  • fmt可以是“hex”、“utf-8”、“base2”或“base64”等不区分大小写的字符串文字。
  • 如果省略,则默认转换的二进制格式为“hex” fmt。

26.数据类型格式化函数:to_numberSPARK-28137

场景介绍

在金融分析或会计系统中,经常会遇到用字符串表示的含有货币单位和千位分隔符的数字。例如,"$1,234.56" 或 "€1.234,56"。在进行数据处理和分析前,需要将这些格式化的字符串转换为数值类型以便进行数学运算。

SQL使用案例

考虑到数据库中有一个名为 financial_records 的表,其中包含两列:id(记录的唯一标识符)和 formatted_amount(表示金额的格式化字符串)。下面是一个使用 to_number 函数将 formatted_amount 列中的字符串转换为数值类型的例子。

在这个例子中,TO_NUMBER(formatted_amount, '999,999,999.99') 函数调用会解析 formatted_amount 中的每一个记录,按照给定的格式模板 '999,999,999.99'(这个模板意味着数字可能包含千位分隔符,并且有两位小数)将其转为数值类型。转换后的数值会在查询结果中的 amount 列显示。

SELECT

    id,

    TO_NUMBER(formatted_amount, '999,999,999.99') AS amount

FROM

    financial_records;

27.添加CONTAINS () 字符串函数 ( SPARK-37508 )

SPARK-37508 是关于在Apache Spark SQL中添加新的CONTAINS()函数的任务。这个函数的目的是为了提供一种常用的方式来检查某个字符串是否包含另一个子串。SQL使用案例

考虑到我们有一个名为social_media_posts的表,它包含两列:id(一个帖子的唯一标识)和content(帖子的文本内容)。我们想要找出所有提及关键词"Spark"的帖子。下面的查询展示了如何使用CONTAINS()函数来实现这一点:

SELECT id, content

FROM social_media_posts

WHERE CONTAINS(content, 'Spark');

28.添加startswith () 和endswith () 字符串函数 ( SPARK-37520 )

SPARK-37520 是关于在Apache Spark SQL中增加两个新的字符串处理函数:startswith()和endswith()的JIRA任务。这两个函数分别用于检查一个字符串是否以指定的子字符串开始或结束,非常适合在处理文本数据时进行模式匹配。

以特定词语开始的反馈:

SELECT id, feedback_text

FROM customer_feedback

WHERE STARTSWITH(feedback_text, '感谢');

以特定词语结束的反馈:

SELECT id, feedback_text

FROM customer_feedback

WHERE ENDSWITH(feedback_text, '再见');

29.支持 split_part 函数(SPARK-38063

SPARK-38063 是Apache Spark SQL中引入split_part()函数的任务。这个函数是许多其他系统(如Postgres)都支持的常用函数。split_part()函数使用户能够从用分隔符分割的字符串中选取特定位置的子串。

提取特定部分的文本:

SELECT split_part(log_entry, ',', 3) AS log_level

FROM logs;

split_part(log_entry, ',', 3)函数将会处理log_entry列的每一个值,使用逗号(,)作为分隔符,然后提取每个字符串的第三部分。

30.向floorceil函数添加 scale 参数( SPARK-37475 )

SPARK-37475 任务的改进是在Spark SQL的FLOOR和CEIL函数中添加了一个比例因子参数(Scale Parameter)。这个改进使得用户能够指定在对数字进行向下取整(FLOOR)或向上取整(CEIL)时要保留的小数位数.

31将 max_by/min_by 添加到 sql.functions(SPARK-36963

-- 假设表格名为 `product_sales`,其中包括 `category`, `product_name`, `sale_price` 列。

-- 目标是为每个商品类别找到售价最高的商品。

SELECT category,

       max_by(product_name, sale_price) AS highest_price_product

FROM product_sales

GROUP BY category;

这个SQL查询的目的是通过max_by函数,对于product_sales表中的每一个category分组,找到sale_price最高的product_name。

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pure-soul

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值