PyODPS proporciona métodos para ejecutar instrucciones SQL de MaxCompute y leer los resultados desde Python.
|
Método |
Propósito |
|
|
Ejecuta SQL de forma síncrona (bloquea hasta que finaliza) |
|
|
Ejecuta SQL de forma asíncrona (devuelve una instancia de inmediato) |
|
|
Lee los resultados de la ejecución de SQL |
No todas las instrucciones SQL se pueden ejecutar medianteexecute_sql()yrun_sql(). Estos métodos admiten instrucciones del lenguaje de definición de datos (DDL) y del lenguaje de manipulación de datos (DML). Utilicerun_security_querypara las instrucciones GRANT o REVOKE, yrun_xflowoexecute_xflowpara las llamadas a la API de XFlow.
Ejecutar instrucciones SQL
Parámetros
|
Parámetro |
Tipo |
Descripción |
|
|
string |
La instrucción SQL que se va a ejecutar |
|
|
dict |
Parámetros de tiempo de ejecución |
Valores devueltos
Tanto execute_sql() como run_sql() devuelven información de Task instances.
Ejemplos
Ejecución síncrona frente a asíncrona
# Synchronous: blocks until the statement finishes
o.execute_sql('select * from table_name')
# Asynchronous: returns immediately
instance = o.run_sql('select * from table_name')
print(instance.get_logview_address()) # Get the LogView URL
instance.wait_for_success() # Block until the statement finishes
Pasar sugerencias de tiempo de ejecución
o.execute_sql('select * from pyodps_iris', hints={'odps.stage.mapper.split.size': 16})
Configuración global
Establezca options.sql.settings para aplicar parámetros de tiempo de ejecución a cada llamada posterior de execute_sql(). Consulte Flag parameters para ver los parámetros disponibles.
from odps import options
options.sql.settings = {'odps.stage.mapper.split.size': 16}
o.execute_sql('select * from pyodps_iris') # Hints apply automatically
Leer los resultados de la consulta
Llame a open_reader() en una instancia finalizada para leer los resultados. El tipo de valor devuelto depende de la instrucción SQL.
Datos estructurados (SELECT)
Las consultas SELECT devuelven registros estructurados. Use un bucle for para iterar sobre cada registro:
with o.execute_sql('select * from table_name').open_reader() as reader:
for record in reader:
print(record)
Datos no estructurados (DESC y otros comandos)
Los comandos como desc devuelven texto sin procesar. Acceda a este mediante reader.raw:
with o.execute_sql('desc table_name').open_reader() as reader:
print(reader.raw)
Interfaz InstanceTunnel frente a Result
De manera predeterminada, open_reader() usa la interfaz Result, la cual puede agotar el tiempo de espera o limitar la cantidad de registros devueltos. Habilite InstanceTunnel para lecturas completas de datos:
Opción 1: configuración global
from odps import options
options.tunnel.use_instance_tunnel = True
Opción 2: parámetro por llamada
with o.execute_sql('select * from table_name').open_reader(tunnel=True) as reader:
for record in reader:
print(record)
En PyODPS V0.7.7.1 y versiones posteriores, open_reader() admite la lectura completa de datos con este enfoque.
Si su versión de MaxCompute es anterior o
InstanceTunnelgenera un error, PyODPS emite una alerta y vuelve automáticamente a la interfazResult. Revise el mensaje de alerta para identificar la causa.Si su versión de MaxCompute solo admite la interfaz
Resulty necesita todos los resultados, escríbalos primero en otra tabla. Después, lea esa tabla conopen_reader(). Este método está sujeto a las restricciones de data protection mechanism de su proyecto.Para obtener más información sobre
InstanceTunnel, consulte InstanceTunnel.
Modo de límite de lectura
De manera predeterminada, PyODPS no limita los datos que se leen de una instancia. Sin embargo, si el propietario del proyecto configuró protección de datos, PyODPS habilita automáticamente el modo de límite de lectura cuando detecta restricciones y options.tunnel.limit_instance_tunnel no está definido. En la mayoría de los casos, este modo restringe la lectura a 10 000 filas.
Habilitar manualmente el modo de límite de lectura (proyectos protegidos):
# Option A: per-call
reader = instance.open_reader(limit=True)
# Option B: global
options.tunnel.limit_instance_tunnel = True
Deshabilite el modo de límite de lectura para acceder a todos los datos:
with o.execute_sql('select * from table_name').open_reader(tunnel=True, limit=False) as reader:
for record in reader:
print(record)
En entornos como DataWorks,options.tunnel.limit_instance_tunnelpuede tener el valor predeterminadoTrue. Para leer todos los datos, pase tantotunnel=Truecomolimit=Falseaopen_reader().
Proyectos protegidos
Si su proyecto está protegido y tunnel=True, limit=False no elimina la restricción, comuníquese con el propietario del proyecto para que le otorgue permisos de lectura. Consulte Project data protection para obtener más detalles.
Usar alias de recursos
Cuando una función definida por el usuario (UDF) hace referencia a recursos que cambian de forma dinámica, configure un alias para asignar el nombre antiguo del recurso a uno nuevo. Así evita eliminar o volver a crear la UDF.
Pase los alias mediante el parámetro aliases en execute_sql():
from odps.models import Schema
myfunc = '''\
from odps.udf import annotate
from odps.distcache import get_cache_file
@annotate('bigint->bigint')
class Example(object):
def __init__(self):
self.n = int(get_cache_file('test_alias_res1').read())
def evaluate(self, arg):
return arg + self.n
'''
res1 = o.create_resource('test_alias_res1', 'file', file_obj='1')
o.create_resource('test_alias.py', 'py', file_obj=myfunc)
o.create_function('test_alias_func',
class_type='test_alias.Example',
resources=['test_alias.py', 'test_alias_res1'])
table = o.create_table(
'test_table',
schema=Schema.from_lists(['size'], ['bigint']),
if_not_exists=True
)
data = [[1, ], ]
# Write one row of data with value 1
o.write_table(table, 0, [table.new_record(it) for it in data])
with o.execute_sql(
'select test_alias_func(size) from test_table').open_reader() as reader:
print(reader[0][0])
res2 = o.create_resource('test_alias_res2', 'file', file_obj='2')
# Map res1 alias to res2 without modifying the UDF or resource
with o.execute_sql(
'select test_alias_func(size) from test_table',
aliases={'test_alias_res1': 'test_alias_res2'}).open_reader() as reader:
print(reader[0][0])
Configurar biz_id
Algunos escenarios requieren un identificador de negocio (biz_id) para ejecutar SQL. Si ocurre un error porque falta el biz_id, establézcalo de forma global:
from odps import options
options.biz_id = 'my_biz_id'
o.execute_sql('select * from pyodps_iris')