Hive:如果我删除当前正在查询的文件会怎样?
Hive: what happens if I delete file that is being queried at the moment?
假设我们有一个 Hive table 作为目录存储在 HDFS 上,如下所示:
data/
|-- file1
|-- file2
|-- file3
如果我开始对该目录进行长时间查询,然后删除其中一个文件,会发生什么情况?
我能想到 3 个场景:
- 文件描述符在开始时打开,数据一直保留到查询结束,即使文件路径不再可用于新查询。
- Hive 会记住文件路径,如果找不到已删除的文件,查询将失败。
- Hive 不会记住文件路径,只会获取当前目录中的文件。
如果 Hive 的行为类似于 (2),并且在查询期间删除文件不安全,从被查询目录中删除旧数据的正确方法是什么 ?
我猜 Hive 会做一个 table 级锁(共享只读)并且它不会允许 table 上的任何 updates/deletes,所以理想情况下它不会允许数据已删除。
也请看看这个post:
Hive Locks entire database when running select on one table
正如@Shankarsh 所述,Hive 尝试在其 Metastore DB 中使用 "lock" table 来协调其查询。尝试 运行 show locks ;
命令,而另一个会话是 运行 长 SELECT 或 INSERT 查询,而另一个会话试图更改 table (必须等待直到可以获取到独占锁)自己看
遗憾的是,这不会阻止 HDFS 直接访问文件和目录。据我所知,HDFS 中只有一种类型的锁,它是用于 create/append/truncate 文件(或现有文件中的最后一个块)的独占锁。
典型场景:您提交查询; Hive 在查询编译时 检索文件和文件块的列表 ,然后启动一些映射器以从这些块中读取;与此同时,另一项工作要求删除其中一个文件 ==> 其中一个映射器将 崩溃 FileNotFoundException
(我去过那里!)
另一个典型场景:...与此同时,另一个作业创建了一个新文件,或者将一个新块附加到现有文件 ==> 该数据将永远不会被访问——顺便说一下,这并不是一件坏事。
底线:避免删除 Hive table(无论是托管的还是外部的)使用的 HDFS 目录中的文件除非您可以确保当前没有查询运行,或者可能很快 运行。如果您想一次删除 所有 个文件,对于托管 table,请在 table/partition 级别使用 TRUNCATE
并让 Hive 进行脏协调东西。
在某些情况下,您可能会尝试使用具有单个分区的临时 table、EXCHANGE PARTITION
Hive 命令(...协调...)的复杂技巧,然后删除 HDFS 在临时目录,然后另一个 EXCHANGE PARTITION
到 return 所有剩余的文件都放回原来的位置——当然,任何在两者之间开始的查询都会看到一个空的 table,这可能是个问题。
假设我们有一个 Hive table 作为目录存储在 HDFS 上,如下所示:
data/
|-- file1
|-- file2
|-- file3
如果我开始对该目录进行长时间查询,然后删除其中一个文件,会发生什么情况?
我能想到 3 个场景:
- 文件描述符在开始时打开,数据一直保留到查询结束,即使文件路径不再可用于新查询。
- Hive 会记住文件路径,如果找不到已删除的文件,查询将失败。
- Hive 不会记住文件路径,只会获取当前目录中的文件。
如果 Hive 的行为类似于 (2),并且在查询期间删除文件不安全,从被查询目录中删除旧数据的正确方法是什么 ?
我猜 Hive 会做一个 table 级锁(共享只读)并且它不会允许 table 上的任何 updates/deletes,所以理想情况下它不会允许数据已删除。
也请看看这个post:
Hive Locks entire database when running select on one table
正如@Shankarsh 所述,Hive 尝试在其 Metastore DB 中使用 "lock" table 来协调其查询。尝试 运行 show locks ;
命令,而另一个会话是 运行 长 SELECT 或 INSERT 查询,而另一个会话试图更改 table (必须等待直到可以获取到独占锁)自己看
遗憾的是,这不会阻止 HDFS 直接访问文件和目录。据我所知,HDFS 中只有一种类型的锁,它是用于 create/append/truncate 文件(或现有文件中的最后一个块)的独占锁。
典型场景:您提交查询; Hive 在查询编译时 检索文件和文件块的列表 ,然后启动一些映射器以从这些块中读取;与此同时,另一项工作要求删除其中一个文件 ==> 其中一个映射器将 崩溃 FileNotFoundException
(我去过那里!)
另一个典型场景:...与此同时,另一个作业创建了一个新文件,或者将一个新块附加到现有文件 ==> 该数据将永远不会被访问——顺便说一下,这并不是一件坏事。
底线:避免删除 Hive table(无论是托管的还是外部的)使用的 HDFS 目录中的文件除非您可以确保当前没有查询运行,或者可能很快 运行。如果您想一次删除 所有 个文件,对于托管 table,请在 table/partition 级别使用 TRUNCATE
并让 Hive 进行脏协调东西。
在某些情况下,您可能会尝试使用具有单个分区的临时 table、EXCHANGE PARTITION
Hive 命令(...协调...)的复杂技巧,然后删除 HDFS 在临时目录,然后另一个 EXCHANGE PARTITION
到 return 所有剩余的文件都放回原来的位置——当然,任何在两者之间开始的查询都会看到一个空的 table,这可能是个问题。