Estou iniciando um novo aplicativo e procurando usar um ORM - em particular, SQLAlchemy.
Digamos que tenho uma coluna 'foo' em meu banco de dados e desejo incrementá-la. No sqlite direto, isso é fácil:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
Eu descobri o equivalente do SQLAlchemy SQL-builder:
engine = sqlalchemy.create_engine('sqlite:///mydata.sqlitedb')
md = sqlalchemy.MetaData(engine)
table = sqlalchemy.Table('stuff', md, autoload=True)
upd = table.update(values={table.c.foo:table.c.foo+1})
engine.execute(upd)
Isso é um pouco mais lento, mas não há muito nele.
Aqui está meu melhor palpite para uma abordagem SQLAlchemy ORM:
# snip definition of Stuff class made using declarative_base
# snip creation of session object
for c in session.query(Stuff):
c.foo = c.foo + 1
session.flush()
session.commit()
Isso faz a coisa certa, mas leva pouco menos de cinquenta vezes mais do que as outras duas se aproximam. Presumo que seja porque ele tem que trazer todos os dados para a memória antes de poder trabalhar com eles.
Existe alguma maneira de gerar o SQL eficiente usando ORM do SQLAlchemy? Ou usando qualquer outro python ORM? Ou devo simplesmente voltar a escrever o SQL manualmente?
python
orm
sqlalchemy
John Fouhy
fonte
fonte
Respostas:
O ORM do SQLAlchemy deve ser usado junto com a camada SQL, e não ocultá-la. Mas você deve manter uma ou duas coisas em mente ao usar o ORM e o SQL simples na mesma transação. Basicamente, de um lado, as modificações de dados ORM só atingirão o banco de dados quando você liberar as alterações de sua sessão. Por outro lado, as instruções de manipulação de dados SQL não afetam os objetos que estão em sua sessão.
Então se você diz
ele fará o que diz, irá buscar todos os objetos do banco de dados, modificará todos os objetos e então quando for a hora de descarregar as alterações no banco de dados, atualizará as linhas uma por uma.
Em vez disso, você deve fazer isso:
Isso será executado como uma consulta como você esperaria, e porque pelo menos a configuração de sessão padrão expira todos os dados na sessão no commit, você não tem nenhum problema de dados obsoletos.
Na série 0.5 quase lançada, você também pode usar este método para atualização:
Isso basicamente executará a mesma instrução SQL do fragmento anterior, mas também selecionará as linhas alteradas e expirará todos os dados obsoletos na sessão. Se você sabe que não está usando nenhum dado de sessão após a atualização, você também pode adicionar
synchronize_session=False
à instrução de atualização e se livrar dessa seleção.fonte
Tente isto =)
fonte
json
colunaExistem várias maneiras de ATUALIZAR usando sqlalchemy
fonte
Aqui está um exemplo de como resolver o mesmo problema sem ter que mapear os campos manualmente:
Portanto, para atualizar uma instância de mídia, você pode fazer algo assim:
fonte
Sem muitos testes, eu tentaria:
(IIRC, commit () funciona sem flush ()).
Eu descobri que às vezes fazer uma grande consulta e, em seguida, iterar em python pode ser até 2 ordens de magnitude mais rápido do que muitas consultas. Presumo que iterar sobre o objeto de consulta é menos eficiente do que iterar sobre uma lista gerada pelo método all () do objeto de consulta.
[Observe o comentário abaixo - isso não agilizou as coisas].
fonte
Se for por causa da sobrecarga em termos de criação de objetos, então provavelmente não pode ser acelerado com o SA.
Se for porque ele está carregando objetos relacionados, talvez você consiga fazer algo com o carregamento lento. Existem muitos objetos sendo criados devido a referências? (Ou seja, obter um objeto Empresa também obtém todos os objetos Pessoas relacionados).
fonte