O PyODPS oferece métodos para criar, ler, gravar e gerenciar tabelas e partições do MaxCompute. Esta página aborda operações comuns em tabelas com exemplos de código executáveis.
Listar todas as tabelas
Chame list_tables() no objeto de entrada para iterar sobre todas as tabelas de um projeto.
for table in odps.list_tables():
# Query all tables in a project.
Verificar se uma tabela existe
Use exist_table() no objeto de entrada para verificar a existência de uma tabela e get_table() para recuperar os metadados da tabela.
t = odps.get_table('table_name')
t.schema
odps.Schema {
c_int_a bigint
c_int_b bigint
c_double_a double
c_double_b double
c_string_a string
c_string_b string
c_bool_a boolean
c_bool_b boolean
c_datetime_a datetime
c_datetime_b datetime
}
t.lifecycle
-1
print(t.creation_time)
2014-05-15 14:58:43
t.is_virtual_view
False
t.size
1408
t.schema.columns
[<column c_int_a, type bigint>,
<column c_int_b, type bigint>,
<column c_double_a, type double>,
<column c_double_b, type double>,
<column c_string_a, type string>,
<column c_string_b, type string>,
<column c_bool_a, type boolean>,
<column c_bool_b, type boolean>,
<column c_datetime_a, type datetime>,
<column c_datetime_b, type datetime>]
O objeto de tabela expõe as seguintes propriedades:
|
Propriedade |
Descrição |
|
|
Objeto |
|
|
Valor do ciclo de vida ( |
|
|
Timestamp de criação da tabela |
|
|
Indica se a tabela é uma visualização virtual |
|
|
Tamanho da tabela em bytes |
|
|
Lista de todos os objetos de coluna |
Crie um schema de tabela
Existem duas abordagens para criar um schema de tabela.
Defina colunas e partições explicitamente
Importe Schema, Column e Partition de odps.models e passe as listas de colunas e partições para o construtor Schema. Esta abordagem aceita o parâmetro comment em cada coluna e partição.
from odps.models import Schema, Column, Partition
columns = [
Column(name='num', type='bigint', comment='the column'),
Column(name='num2', type='double', comment='the column2'),
]
partitions = [Partition(name='pt', type='string', comment='the partition')]
schema = Schema(columns=columns, partitions=partitions)
Após criar um schema, inspecione seu conteúdo com estas propriedades:
-
Todas as colunas (incluindo colunas de chave de partição): Saída:
print(schema.columns)[<column num, type bigint>, <column num2, type double>, <partition pt, type string>] -
Apenas colunas de chave de partição: Saída:
print(schema.partitions)[<partition pt, type string>] -
Nomes das colunas sem partição: Saída:
print(schema.names)['num', 'num2'] -
Tipos de dados das colunas sem partição: Saída:
print(schema.types)[bigint, double]
Usar Schema.from_lists()
O método Schema.from_lists() é um atalho que aceita listas de nomes e tipos. Embora mais simples, ele não suporta comentários de coluna ou partição diretamente.
from odps.models import Schema
schema = Schema.from_lists(['num', 'num2'], ['bigint', 'double'], ['pt'], ['string'])
print(schema.columns)
Saída:
[<column num, type bigint>,
<column num2, type double>,
<partition pt, type string>]
Crie uma tabela
Para criar uma tabela, chame o.create_table(). Certifique-se de que todos os tipos de dados das colunas sejam válidos. Há duas formas de fazer isso: passar um objeto Schema ou passar as definições das colunas como strings.
Crie uma tabela a partir de um schema
Construa primeiro um Schema e depois passe-o para create_table().
# Create a table schema.
from odps.models import Schema
schema = Schema.from_lists(['num', 'num2'], ['bigint', 'double'], ['pt'], ['string'])
# Create a table by using the schema that you created.
table = o.create_table('my_new_table', schema)
# Create a table only if no table with the same name exists.
table = o.create_table('my_new_table', schema, if_not_exists=True)
# Configure the lifecycle of the table.
table = o.create_table('my_new_table', schema, lifecycle=7)
Verifique se a tabela foi criada:
print(o.exist_table('my_new_table'))
Se o retorno for True, a tabela foi criada com sucesso.
Crie uma tabela a partir de definições de coluna
Passe os nomes e tipos de dados das colunas como uma string ou tupla para create_table().
# Create a partitioned table named my_new_table with specified common columns and partition key columns.
table = o.create_table('my_new_table', ('num bigint, num2 double', 'pt string'), if_not_exists=True)
# Create a non-partitioned table named my_new_table02.
table = o.create_table('my_new_table02', 'num bigint, num2 double', if_not_exists=True)
Verifique se a tabela foi criada:
print(o.exist_table('my_new_table'))
Caso o resultado seja True, a criação da tabela ocorreu corretamente.
Ative tipos de dados estendidos do MaxCompute V2.0
Por padrão, create_table() suporta apenas os tipos de dados BIGINT, DOUBLE, DECIMAL, STRING, DATETIME, BOOLEAN, MAP e ARRAY. Para utilizar outros tipos, como TINYINT e STRUCT, defina options.sql.use_odps2_extension como True.
from odps import options
options.sql.use_odps2_extension = True
table = o.create_table('my_new_table', 'cat smallint, content struct<title:varchar(100), body:string>')
Exclua uma tabela
Chame delete_table() no objeto de entrada ou invoque drop() em um objeto de tabela.
o.delete_table('my_table_name', if_exists=True) # Delete a table only if the table exists.
t.drop() # Call the drop() method to drop a table if the table exists.
Gerencie partições de tabela
Verificar se uma tabela é particionada
table = o.get_table('my_new_table')
if table.schema.partitions:
print('Table %s is partitioned.' % table.name)
Iterar sobre partições
table = o.get_table('my_new_table')
for partition in table.partitions: # Iterate over all partitions.
print(partition.name) # An iteration step. In this step, the partition name is displayed.
for partition in table.iterate_partitions(spec='pt=test'): # Iterate over level-2 partitions in the partition named test.
print(partition.name) # An iteration step. In this step, the partition name is displayed.
for partition in table.iterate_partitions(spec='dt>20230119'): # Iterate over level-2 partitions in the partitions that meet the dt>20230119 condition.
print(partition.name) # An iteration step. In this step, the partition name is displayed.
Expressões lógicas em iterate_partitions (como dt>20230119) exigem PyODPS 0.11.3 ou superior.
Verificar se uma partição existe
table = o.get_table('my_new_table')
table.exist_partition('pt=test,sub=2015')
Obter informações da partição
table = o.get_table('my_new_table')
partition = table.get_partition('pt=test')
print(partition.creation_time)
partition.size
Crie uma partição
t = o.get_table('my_new_table')
t.create_partition('pt=test', if_not_exists=True) # Create a partition only if no partition with the same name exists.
Exclua uma partição
t = o.get_table('my_new_table')
t.delete_partition('pt=test', if_exists=True) # Set the if_exists parameter to True. This ensures that a partition is deleted only if the partition exists.
partition.drop() # Call the drop() method to drop a partition if the partition exists.
Ler dados de uma tabela
Ler os primeiros N registros com head()
O método head() recupera até 10.000 registros de uma tabela.
from odps import ODPS
t = o.get_table('dual')
for record in t.head(3):
# Process each record.
Leitura com open_reader() usando instrução with
with t.open_reader(partition='pt=test') as reader:
count = reader.count
for record in reader[5:10] # You can execute the statement multiple times until all records are read. The number of records is specified by count. You can change the code to parallel-operation code.
# Process one record.
Leitura com open_reader() sem instrução with
reader = t.open_reader(partition='pt=test')
count = reader.count
for record in reader[5:10] # You can execute the statement multiple times until all records are read. The number of records is specified by count. You can change the code to parallel-operation code.
# Process one record.
Ler diretamente em um DataFrame do pandas
with t.open_reader(partition='pt=test') as reader:
pd_df = reader.to_pandas()
Gravar dados em uma tabela
Gravar com open_writer() usando instrução with
with t.open_writer(partition='pt=test') as writer:
records = [[111, 'aaa', True], # A list can be used.
[222, 'bbb', False],
[333, 'ccc', True],
[444, 'Chinese', False]]
writer.write(records) # Records can be iterable objects.
records = [t.new_record([111, 'aaa', True]), # Record objects can be used.
t.new_record([222, 'bbb', False]),
t.new_record([333, 'ccc', True]),
t.new_record([444, 'Chinese', False])]
writer.write(records)
É possível passar listas simples ou objetos Record (criados com t.new_record()) para writer.write().
Crie partição automaticamente durante a gravação
Defina create_partition=True para criar a partição automaticamente caso ela não exista.
with t.open_writer(partition='pt=test', create_partition=True) as writer:
records = [[111, 'aaa', True], # A list can be used.
[222, 'bbb', False],
[333, 'ccc', True],
[444, 'Chinese', False]]
writer.write(records) # Records can be iterable objects.
Gravar com write_table()
O método write_table() no objeto de entrada do MaxCompute oferece uma interface mais simples para gravação de dados.
records = [[111, 'aaa', True], # A list can be used.
[222, 'bbb', False],
[333, 'ccc', True],
[444, 'Chinese', False]]
o.write_table('test_table', records, partition='pt=test', create_partition=True)
Ler e gravar dados no formato Apache Arrow
O Apache Arrow é um formato multilinguagem para troca de dados entre diferentes plataformas. O MaxCompute suporta leitura de dados de tabela no formato Arrow desde 2021. O PyODPS 0.11.2 e versões posteriores também suportam esse recurso.
Após instalar o pyarrow em seu ambiente Python, adicione arrow=True ao chamar open_reader() ou open_writer() para ler ou gravar objetos RecordBatch do Arrow.
import pandas as pd
import pyarrow as pa
with t.open_writer(partition='pt=test', create_partition=True, arrow=True) as writer:
records = [[111, 'aaa', True],
[222, 'bbb', False],
[333, 'ccc', True],
[444, 'Chinese', False]]
df = pd.DataFrame(records, columns=["int_val", "str_val", "bool_val"])
# Write a RecordBatch.
batch = pa.RecordBatch.from_pandas(df)
writer.write(batch)
# You can also use Pandas DataFrame directly.
writer.write(df)