批量查询HIVE所有表的大小和行数

概述

  • 需求:
    1、批量查询HIVE表的大小和行数
    2、批量查询HIVE表文件数和分区数
  • 思路
    借助程序(本文为Python2)遍历HIVE表,DESC FORMATTED获取表状态信息
  • 我们往往不需要所有表,而是指定的表,筛选方法:
    1、制定表名规则,USE 库+SHOW TABLES+LIKE进行筛选
    2、在MySQL(HIVE元数据存储位置)进行筛选

批量获取HIVE表基本信息

SELECT
    b.`NAME`,           -- 库名
    t.`TBL_NAME`,       -- 表名
    t.`TBL_TYPE`,       -- 表类型
    c.`PARAM_VALUE`,    -- 表注释
    s.`LOCATION`        -- 表的HDFS路径
FROM `DBS`b
INNER JOIN `TBLS`t ON t.`DB_ID`=b.`DB_ID`
INNER JOIN `SDS`s ON s.`SD_ID`=t.`SD_ID`
LEFT JOIN (
    SELECT `TBL_ID`,`PARAM_VALUE`
    FROM `TABLE_PARAMS`
    WHERE `PARAM_KEY`='comment'
)c ON c.`TBL_ID`=t.`TBL_ID`
WHERE t.`TBL_TYPE`='MANAGED_TABLE' OR t.`TBL_TYPE`='EXTERNAL_TABLE';

详细信息

SELECT
    b.`NAME` AS `库名`
    ,t.`TBL_NAME` AS `表名`
    ,t.`TBL_TYPE` AS `表类型`
    ,c.`PARAM_VALUE` AS `表注释`
    ,s.`LOCATION` AS `表的HDFS路径`
    ,t.`VIEW_EXPANDED_TEXT` AS `视图的SQL`
    ,t.`OWNER` AS `表的属主`
    ,t.`OWNER_TYPE` AS `表的属主的类型`
    ,s.`INPUT_FORMAT` AS `表输入格式`
    ,s.`OUTPUT_FORMAT` AS `表输出格式`
    -- ,s.`NUM_BUCKETS` AS `分桶数`
    -- ,s.`IS_COMPRESSED` AS 是否压缩
FROM `DBS`b
INNER JOIN `TBLS`t ON t.`DB_ID`=b.`DB_ID`
INNER JOIN `SDS`s ON s.`SD_ID`=t.`SD_ID`
LEFT JOIN (
    SELECT `TBL_ID`,`PARAM_VALUE`
    FROM `TABLE_PARAMS`
    WHERE `PARAM_KEY`='comment'
)c ON c.`TBL_ID`=t.`TBL_ID`
WHERE t.`TBL_TYPE`='MANAGED_TABLE' OR t.`TBL_TYPE`='EXTERNAL_TABLE';

查询单个HIVE表的大小和行数

DESC FORMATTED 库名.表名;

代码

MySQL建表,用于存储查询结果

USE data_management;
CREATE TABLE hive_table_status(
  update_time     TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP,
  table_name
<think>我们之前讨论了如何批量写入Hive,现在用户明确要求通过“批量循环”写入,即分批次将数据插入Hive。结合之前的讨论引用,关键点如下:1.引用[1]提醒:执行INSERT语句后不能调用fetch方法,否则会报错(Noresultset)。2.之前的最佳实践提到:小批量数据用VALUES子句,大批量用文件加载。3.用户要求“批量循环”写入,所以这里我们采用分批次执行SQL插入的方式。实现思路:-将大数据集拆分成多个批次(例如每批500条)。-对于每个批次,构建一个包含多条记录的INSERT语句(使用VALUES子句)。-执行每个INSERT语句,并注意不调用fetch方法。注意:Hive的INSERT语句每次执行都会生成一个HDFS文件,所以批次数量不宜过多(否则小文件过多),但也要避免单个SQL过大(内存超时问题)。因此批次大小需要权衡。示例代码步骤:1.连接Hive(保持长连接,避免循环内重复连接)。2.准备数据,分批次(例如每批500条)。3.对每个批次:a.构建一个INSERT语句,包含多个VALUES。b.执行SQL(不调用fetch)。c.错误处理(如重试)。4.关闭连接。注意:字符串需要转义(特别是单引号),防止SQL错误。代码实现:```pythonimportpyhive.hiveashiveimporttimedefbatch_insert_in_loops(data,batch_size=500):"""批量循环插入数据到HiveArgs:data:数据列每个元素是元组(对应一行)batch_size:每批次的行数,默认为500"""conn,cursor=None,Nonetry:conn=hive.Connection(host='hive-server',port=10000,username='hive_user')cursor=conn.cursor()total=len(data)num_batches=(total+batch_size-1)//batch_size#计算批次数量foriinrange(num_batches):start=i*batch_sizeend=min((i+1)*batch_size,total)batch=data[start:end]#构建VALUES部分:每个元组转成字符串,并转义单引号values_list=[]forrowinbatch:#假设每行数据是(id,name)的形式,且name是字符串#将单引号转义为两个单引号(Hive使用单引号示字符串)escaped_row=[]foriteminrow:ifisinstance(item,str):item=item.replace("'","''")#转义单引号escaped_row.append(f"'{item}'")else:escaped_row.append(str(item))values_list.append("("+",".join(escaped_row)+")")values_str=",".join(values_list)sql=f"INSERTINTOyour_table(id,name)VALUES{values_str}"#替换列名try:cursor.execute(sql)#注意:不fetch结果,避免错误print(f"第{i+1}批数据插入成功({len(batch)}条)")exceptExceptionase:#这里可以根据需要加入重试机制print(f"第{i+1}批插入失败:{e}")#可以选择记录失败批次,后续重试#这里简单跳过,实际应用需处理#也可以考虑回滚或中断#可选:批次间延迟(根据Hive集群压力调整)#time.sleep(0.1)exceptExceptionase:print(f"发生全局错误:{e}")finally:ifcursor:cursor.close()ifconn:conn.close()if__name__=="__main__":#假设我们有10000条数据importrandomimportstring#生成测试数据data=[]foriinrange(10000):#生成随机字符串(假设name字段)name=''.join(random.choices(string.ascii_letters,k=10))data.append((i,name))batch_insert_in_loops(data,batch_size=500)```重要说明:1.列名:在SQL中替换`your_table`列名(如`(id,name)`)为实际结构。2.数据类型处理:示例仅处理了整型字符串。其他类型(如日期)需要相应转换。3.转义:字符串中的单引号被转义为两个单引号(Hive使用单引号),注意其他特殊字符(如反斜杠)可能也需要转义。4.错误处理:当前仅打印错误,实际生产环境需更健壮(如重试机制、事务等)。5.性能:批量大小(batch_size)需要根据数据行宽集群性能调整,避免SQL过长。建议500~2000行每批。6.小文件问题:批次过多会导致HDFS小文件问题,可通过在循环结束后合并(如执行`ALTERTABLE...CONCATENATE`)或在设计中设置合适的分区/分桶来缓解。替代方案(如果数据量极大):如果数据量非常大,推荐使用先将数据写入HDFS文件,然后一次性加载到Hive的方法,避免循环插入带来的小文件问题。但用户明确要求“批量循环”,所以此代码按照要求给出。如果用户允许,可以结合两种方式:循环中每次写入一个临时文件,然后加载(这样每个批次生成一个文件),最后再合并。但代码将更复杂。相关问题:1.如何避免循环插入Hive时产生的小文件问题?2.在批量循环插入时,如何实现错误重试机制?3.对于不同类型的数据(如日期、时间戳、二进制),在构建插入SQL时应该如何安全处理?4.如何监控循环插入的进度性能?</think> 要使用 Python 通过批量循环向 Hive 写入数据,核心思路是**将大数据集分割成较小批次,每次循环执行一批数据的插入操作**。以下是基于引用[1]最佳实践的解决方案: ### 批量循环写入 HivePython 实现 ```python import pyhive.hive as hive import time def batch_insert_loop(data, batch_size=100, max_retries=3): """ 批量循环插入数据到Hive 参数: data: 要插入的数据列(格式:[(id1, name1), (id2, name2), ...]) batch_size: 每批插入的数据量 max_retries: 单次插入失败的最大重试次数 """ try: # 创建Hive连接 conn = hive.Connection( host='your_hive_host', port=10000, username='your_username' ) cursor = conn.cursor() # 计算批次数量 total = len(data) num_batches = (total + batch_size - 1) // batch_size # 循环处理每个批次 for i in range(num_batches): start = i * batch_size end = min((i+1) * batch_size, total) batch = data[start:end] attempts = 0 success = False # 带有重试机制的批次插入 while not success and attempts < max_retries: try: # 构建SQL VALUES子句 values_list = [] for record in batch: # 转义单引号防止SQL错误 escaped = tuple( str(item).replace("'", "''") if isinstance(item, str) else item for item in record ) values_list.append(str(escaped)) values_str = ",".join(values_list) # 创建INSERT语句 sql = f"INSERT INTO your_table (id, name) VALUES {values_str}" # 替换实际列名 # 执行插入(重要:不获取结果集) cursor.execute(sql) # 记录成功状态 success = True print(f"批次 {i+1}/{num_batches}: 插入 {len(batch)} 条数据成功") except hive.exc.ProgrammingError as e: # 处理无结果集错误(INSERT操作成功但无返回) if "No result set" in str(e): success = True # 实际插入成功 print(f"批次 {i+1}/{num_batches}: 插入成功(无结果返回)") else: print(f"批次 {i+1} SQL错误: {e}") attempts += 1 time.sleep(2**attempts) # 指数退避重试 except Exception as e: print(f"批次 {i+1} 发生错误: {e}") attempts += 1 time.sleep(2**attempts) # 指数退避重试 if not success: print(f"警告: 批次 {i+1} 插入失败(尝试次数超过限制)") # 此处可添加错误批次记录逻辑 print(f"全部数据插入完成,共插入 {total} 条数据") except Exception as e: print(f"全局错误: {e}") finally: # 清理资源 if 'cursor' in locals(): cursor.close() if 'conn' in locals(): conn.close() # 使用示例 if __name__ == "__main__": # 生成10,000条测试数据 test_data = [(i, f"Name_{i}") for i in range(10000)] # 执行批量循环插入(每批500条) batch_insert_loop(test_data, batch_size=500) ``` ### 关键实现细节解释 1. **分批次处理**: - 将大数据集分割为可管理的小批次(默认每批100-500条) - 使用循环逐批处理数据 `for i in range(num_batches)` 2. **安全转义处理**: ```python escaped = tuple(str(item).replace("'", "''") if isinstance(item, str) else item... ``` - 对字符串中的单引号进行转义处理,防止SQL注入语法错误 3. **错误处理机制**: - 捕获 `ProgrammingError` 并特别处理 `No result set` 警告[^1] - 实现指数退避重试机制 `time.sleep(2**attempts)` - 限制最大重试次数防止无限循环 4. **结果集处理**: - 避免调用 `fetchall()` 或 `fetchone()`,因为INSERT操作不返回结果集[^1] - 通过异常处理区分实际错误成功警告 5. **资源管理**: - 使用 `try/finally` 确保连接关闭 - 批处理中保持同一连接,避免频繁开关连接 ### 性能优化建议 1. **批量大小调整**: ```python # 根据网络延迟集群性能调整批次大小 optimal_batch = 200 # 在100-500之间根据测试结果调整 ``` 2. **并行处理**: - 使用多线程/协程同时处理多个批次(需要Hive会话支持) 3. **连接池管理**: - 对大规模数据,使用连接池减少创建连接开销 4. **进度监控**: ```python # 添加进度日志 if i % 10 == 0: print(f"进度: {(i+1)*batch_size}/{total} ({round(((i+1)*batch_size/total)*100, 1)}%)") ``` 5. **持久化断点**: - 记录失败批次,支持断点续传 - 将失败批次保存到文件或数据库
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小基基o_O

您的鼓励是我创作的巨大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值