程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python trino執行hive insert overwrite不生效的問題

編輯:Python

使用python的trino包執行insert overwrite,但是overwrite卻沒有生效的問題

根據trino的官網介紹的insert overwrite的開啟方式,開啟hive的insert overwrite會話,使當前會話的insert into語句支持insert overwrite,也即支持插入數據根據分區覆蓋更新的功能

但是在使用Python代碼執行時總是沒有生效,在花了不少時間debug之後,終於找到了原因竟是因為開啟insert overwrite session的語句沒有執行fetchall()而導致沒有生效

下面是執行的的代碼示例

import trino
def insert_overwrite_query(trino, ...):
conn = trino.dbapi.connect()
cursor: Cursor = conn.cursor()
overwrite_sql = "SET SESSION hive.insert_existing_partitions_behavior = 'OVERWRITE'"
cursor.execute(overwrite_sql)
query = """insert into hive.schema.table ..."""
cursor.execute(query)
res = cursor.fetchall()
...

overwrite_sql在執行之後需要執行cursor.fetchall()才會生效,在此之前實在不明白這條sql為什麼需要fetchall()?fetchall()的作用不是在需要返回數據時才執行嗎?

在一番搜尋之後才了解到fetchall()的真正運作機制

  • 通常查詢的結果集會存儲在內存之中,好的數據庫連接處理一般會將查詢結果集存放在服務端的內存,在接收請求時才會返回給客戶端,也就是說只有在執行fetchall()之後前面的insert overwrite session也會確切地被執行

另外就是python trino中的fetchall()的作用了,一番源碼觀察之後,確定了trino的查詢機制

  • 查詢是分批次查詢的,數據量大的數據會首先使用post請求查詢一批數據,然後接下來如果客戶端還需要剩余的結果,會使用get請求查詢接下來的所有數據之後結束或者連接中斷

根據cursor.fetchall() 找到了其數據實際上來自於一個生成器對象TrinoResult,在fetchall()的時候實際上執行了list(TrinoResult(...))取得了查詢結果(實際上你執行list(cursor.execute(query))也會得到fetchall()相同的結果)

class TrinoResult(object):
def __init__(self, query, rows=None, experimental_python_types: bool = False):
self._query = query
self._rows = rows or []
self._rownumber = 0
self._experimental_python_types = experimental_python_types
...
def __iter__(self):
# Initial fetch from the first POST request
for row in self._rows:
self._rownumber += 1
yield row
self._rows = None
# Subsequent fetches from GET requests until next_uri is empty.
while not self._query.finished:
rows = self._query.fetch()
for row in rows:
self._rownumber += 1
logger.debug("row %s", row)
if not self._experimental_python_types:
yield row
else:
yield self._map_to_python_types(row, self._query.columns)

總之,在session sql後面需要在執行一次fetchall()才會使開啟session的sql生效,但是總覺得有點不符合直覺


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved