Ambas as estratégias de carregamento problemáticas geram exceções se você tentar usá-las com
yield_per
, então você realmente não precisa se preocupar muito. Eu acredito o único problema com
subqueryload
é que o carregamento em lote da segunda consulta não foi implementado (ainda). Nada daria errado semanticamente, mas se você estiver usando yield_per
, você provavelmente tem um bom motivo para não querer carregar todos os resultados de uma vez. Então SQLAlchemy educadamente se recusa a ir contra seus desejos. joinedload
é um pouco mais sutil. Só é proibido no caso de uma coleção, onde uma linha primária pode ter várias linhas associadas. Digamos que sua consulta produza resultados brutos como este, onde A e B são chaves primárias de tabelas diferentes: A | B
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 5
2 | 6
Agora você os busca com
yield_per(3)
. O problema é que o SQLAlchemy só pode limitar o quanto ele busca por linhas , mas deve retornar objetos . Aqui, SQLAlchemy vê apenas as três primeiras linhas, então cria um A
objeto com chave 1 e três B
filhos:1, 2 e 3. Quando ele carrega o próximo lote, ele deseja criar um novo
A
objeto com chave 1... ah, mas ele já tem uma dessas, então não precisa criar novamente. O B
extra , 4, é perdido. (Então, não, mesmo lendo coleções unidas com yield_per
não é seguro — pedaços de seus dados podem desaparecer.) Você pode dizer "bem, continue lendo as linhas até ter um objeto completo" - mas e se esse
A
tem cem filhos? Ou um milhão? SQLAlchemy não pode garantir razoavelmente que pode fazer o que você pediu e produzir resultados corretos, por isso se recusa a tentar. Lembre-se de que a DBAPI foi projetada para que qualquer banco de dados pode ser usado com a mesma API, mesmo que esse banco de dados não suporte todos os recursos DBAPI. Considere que a DBAPI é projetada em torno de cursores, mas o MySQL na verdade não tem cursores! Os adaptadores DBAPI para MySQL precisam falsificá-los.
Então, enquanto
cursor.fetchmany(100)
vai funcionar , você pode ver no o MySQLdb código-fonte
que não busca preguiçosamente do servidor; ele busca tudo em uma grande lista e retorna uma fatia quando você chama fetchmany
. O que
psycopg2
suporta é o verdadeiro streaming, onde os resultados são lembrados persistentemente no servidor, e seu processo Python vê apenas alguns deles por vez. Você ainda pode usar
yield_per
com MySQLdb
, ou qualquer outro DBAPI; esse é o ponto principal do design do DBAPI. Você terá que pagar o custo de memória para todas as linhas brutas ocultas na DBAPI (que são tuplas, bastante baratas), mas não também tem que pagar por todos os objetos ORM ao mesmo tempo.