记一次生产环境presto删表失败的问题

博客讲述使用Java程序连接Presto创建并删除Hive表时遇到权限问题。用Presto删表报错,直连Hive删表正常。通过连接Hive元数据MySQL查询,发现Presto默认用户与存储用户不一致。最终解决方法是修改jmx.config并以common用户启动Presto。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景,开发用java程序连接presto创建一个表,这个表在hdfs的权限为:

然后用presto去删除这个表

报错,没有权限删除,查看上一级目录权限,发现权限正常

直连hive删表

发现正常. 然后使用developer直连hive 创建表,用presto删除还是报错没有权限。

 

连接hive 元数据MySQL  

select t.OWNER, p.PRINCIPAL_NAME, count(1)  from TBLS t      join TBL_PRIVS p on p.TBL_ID=t.TBL_ID  group by t.OWNER, p.PRINCIPAL_NAME;

再次用presto(jmx.configure

 

)创建表

 

 发现 common对应的count增加了,但是developer的没有增加。

 

问题就明了了。 presto默认是以启动presto的用户来做hive元数据的也就是这里的common用户, 但是存储用户是以jmx.configure 里面配置的用户来设定的。所以 在presto里面(developer用户进入)删除这个表会提示权限不够

 

解决方法修改 jmx.config

然后以common用户启动presto

 

转载于:https://www.cnblogs.com/ZFBG/p/10951211.html

<think>我们正在讨论PrestoSQL中的函数,特别是如何获取字段中最后一次出现的值。在Presto中,没有直接名为“lastoccurrence”的函数,但我们可以通过其他方式实现。通常,要获取某个字段在分组内最后一次出现的值,我们可以使用窗口函数,结合排序条件来取最后一条录。常见的方法是使用`last_value`窗口函数,但需要注意,窗口函数需要指定窗口框架(windowframe),因为默认的窗口框架是从分区的第一行到当前行,所以如果我们想要整个分区的最后一行,我们需要调整窗口框架。另一种方法是使用`array_agg`函数配合排序,然后取数组的最后一个元素。具体实现:1.使用窗口函数`last_value`,并指定窗口框架为整个分区(ROWSBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING):```sqlSELECTlast_value(column_name)OVER(PARTITIONBYpartition_columnORDERBYorder_columnROWSBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)ASlast_valueFROMtable_name;```但是,请注意,`last_value`函数在默认的窗口框架下(即不指定ROWSBETWEEN)只会取到当前行为止的最后一个值,而不是整个分区的最后一个值。因此,我们必须指定窗口框架为整个分区。2.使用`array_agg`和`array_max`(或通过下标访问):```sqlSELECTarray_agg(column_nameORDERBYorder_columnDESC)[1]ASlast_valueFROMtable_nameGROUPBYpartition_column;```或者,更直接地,使用`slice`和`array_agg`,但Presto中数组下标从1开始,我们可以取数组的第一个元素(因为我们按倒序排列,所以第一个元素就是最后一个出现的值)。注意:如果分组后数组可能为空,需要处理。然而,在Presto中,我们也可以使用`reduce`或`max_by`等函数,但这里更推荐窗口函数或数组聚合。但是,请注意:用户要求的是“最后一次出现”,即按某种顺序(如时间顺序)的最后一个值。另外,Presto还提供了一个函数`nth_value`,可以取第n个值,但同样需要窗口框架。考虑到性能和可读性,通常使用窗口函数更为直接。因此,我们给出一个示例:假设我们有一个`sales`,包含字段`sale_date`(销售日期)、`product_id`(产品ID)和`price`(价格),我们想要获取每个产品最新的价格(即按日期排序,最后一次出现的价格)。方法1:使用窗口函数```sqlSELECTDISTINCTproduct_id,last_value(price)OVER(PARTITIONBYproduct_idORDERBYsale_dateROWSBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)ASlast_priceFROMsales;```注意:这里使用了DISTINCT,因为窗口函数会为每一行都返回一个值,而我们只需要每个产品一条录。也可以使用子查询去重。方法2:使用聚合函数```sqlSELECTproduct_id,array_agg(priceORDERBYsale_dateDESC)[1]ASlast_priceFROMsalesGROUPBYproduct_id;```两种方法都可以,但第二种方法在分组聚合时可能更高效。另外,Presto还提供了`max_by`函数,但是`max_by`是取与最大值对应的那个值,如果我们按日期取最大值,那么对应的价格就是最后一次的价格吗?注意:如果日期是递增的,那么最大日期对应的价格就是最后一次出现的价格。所以:方法3:使用`max_by`函数(需要先按产品分组,然后取最大日期对应的价格)```sqlSELECTproduct_id,max_by(price,sale_date)ASlast_priceFROMsalesGROUPBYproduct_id;```但是,注意:`max_by`函数返回的是与最大sale_date对应的price。如果有多个相同的最大sale_date,那么它会返回其中任意一个(非确定)。如果我们的需求是取最后一次出现的值,且按日期排序,那么最大日期对应的价格就是最后一次出现的价格。因此,这个方法很合适。结论:在Presto中,获取字段最后一次出现的值(按某个顺序)可以使用以下方法:1.窗口函数`last_value`配合正确的窗口框架(整个分区)2.使用`array_agg`取倒序后的第一个元素3.使用`max_by`函数(如果排序的字段是数值或日期,且我们要取最大值对应的那个字段值)根据场景选择最合适的方法。因此,针对用户的问题,我们可以推荐使用`max_by`函数,因为它简洁且易于理解,但前提是我们要按一个可以取最大值的列来排序(比如时间戳、日期、数字等)。如果排序的列不是最大值而是最小值,那么我们可以使用`min_by`,或者通过排序调整。但是,如果“最后一次”是指数据插入的顺序,而我们没有一个明确的排序字段,那么可能需要使用其他方法(如row_number等)。但用户的问题中,应该有一个隐含的排序字段(如时间字段)。所以,我们假设用户有一个排序字段,那么使用`max_by`是最直接的。示例:获取每个用户最后一次登录的IP地址```sqlSELECTuser_id,max_by(ip_address,login_time)ASlast_login_ipFROMlogin_logsGROUPBYuser_id;```如果用户没有分组,而是想要在整个中某个字段的最后一次出现的值(没有分区),那么我们可以使用全局排序,例如:```sqlSELECTmax_by(column_name,order_column)FROMtable_name;```或者,如果整个只取一个值,也可以:```sqlSELECTcolumn_nameFROMtable_nameORDERBYorder_columnDESCLIMIT1;```因此,根据上下文,选择合适的方法。现在,我们来生成相关问题。</think>在 Presto SQL 中,获取字段最后一次出现的值通常需要使用**窗口函数**结合排序逻辑实现。虽然没有名为 `last_occurrence` 的专用函数,但可通过以下方法实现: ### 方法 1:使用 `last_value()` 窗口函数 通过指定窗口框架范围获取分组内最后一个值: ```sql SELECT id, value, -- 按时间倒序排序,取分区内最后一个值 last_value(value) OVER ( PARTITION BY id ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS last_occurrence_value FROM your_table; ``` **关键点**: - `PARTITION BY id`:按分组字段分区(如用户ID) - `ORDER BY timestamp DESC`:按时间戳**倒序排列**(确保最后出现值在末尾) - `ROWS BETWEEN ...`:指定窗口覆盖整个分区(必须显式声明) --- ### 方法 2:使用 `array_agg()` 聚合函数 通过数组聚合取最后一个元素: ```sql SELECT id, -- 按时间正序聚合后取数组最后一个元素 element_at(array_agg(value ORDER BY timestamp), -1) AS last_occurrence_value FROM your_table GROUP BY id; ``` **优势**:语法更简洁,适合分组聚合场景。 --- ### 方法 3:使用 `row_number()` + 子查询 ```sql SELECT id, value AS last_occurrence_value FROM ( SELECT *, row_number() OVER (PARTITION BY id ORDER BY timestamp DESC) AS rn FROM your_table ) WHERE rn = 1; -- 取排序后的第一条(即时间倒序的首条) ``` --- ### 场景示例 假设 `user_actions` 录用户行为: | user_id | action | action_time | |---------|---------|----------------------| | 101 | login | 2023-01-01 10:00:00 | | 101 | click | 2023-01-01 11:30:00 | | 101 | logout | 2023-01-01 12:00:00 | 获取每个用户最后一次的 `action`: ```sql SELECT user_id, last_value(action) OVER ( PARTITION BY user_id ORDER BY action_time DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS last_action FROM user_actions GROUP BY user_id, action, action_time; ``` **结果**: | user_id | last_action | |---------|-------------| | 101 | logout | --- ### 注意事项 1. **明确排序字段**:必须指定时间戳或序列字段(如 `ORDER BY timestamp DESC`) 2. **窗口框架声明**:使用 `last_value()` 时务必包含 `ROWS BETWEEN ...` 子句 3. 性能优化:对大数据集优先使用 `array_agg()` 或 `row_number()` 方法 > 参考 Presto 窗口函数文档:[Window Functions - Presto Documentation](https://prestodb.io/docs/current/functions/window.html)[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值