使用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()的真正運作機制
另外就是python trino中的fetchall()的作用了,一番源碼觀察之後,確定了trino的查詢機制
根據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生效,但是總覺得有點不符合直覺