ce problème dépend de la quantité de données non-ASCII que vous traitez. La méthode de décodage d'unicode de psycopg2 est plus rapide que celle de SQLAlchemy, en supposant que les extensions C de SQLA ne sont pas utilisées, mais ajoute encore de la latence pour un ensemble de résultats par rapport à ne pas effectuer de conversion unicode. Dans le code ci-dessus, les fonctionnalités Unicode de SQLAlchemy ne sont pas utilisées; elles sont uniquement utilisées lorsqu'une colonne est mappée sur les types Unicode ou String, ce qui ne peut se produire que si vous utilisez text(), select() ou un équivalent ORM, où un type Unicode est mappé à ces colonnes de jeu de résultats en utilisant les métadonnées Table le paramètre "typemap" de text(). Les fonctions Unicode natives de Psycopg2 OTOH prennent effet au niveau du curseur. Elles sont toujours actives et ajoutent apparemment une latence globale.
Voici une série d'illustrations du fonctionnement des différentes méthodes. le dernier est le plus semblable à celle de SQLAlchemy, bien que lors de l'utilisation des extensions C de sqlalchemy nous sommes probablement un jeûne comme psycopg2:
import psycopg2
from psycopg2 import extensions
conn = psycopg2.connect(user='scott', password='tiger', host='localhost', database='test')
cursor = conn.cursor()
cursor.execute("""
create table data (
id SERIAL primary key,
data varchar(500)
)
""")
cursor.executemany("insert into data (data) values (%(data)s)", [
{"data":"abcdefghij" * 50} for i in xrange(10000)
])
cursor.close()
def one(conn):
cursor = conn.cursor()
cursor.execute("SELECT data FROM data")
for row in cursor:
row[0]
def two(conn):
cursor = conn.cursor()
extensions.register_type(extensions.UNICODE, cursor)
cursor.execute("SELECT data FROM data")
for row in cursor:
row[0]
def three(conn):
cursor = conn.cursor()
cursor.execute("SELECT data FROM data")
for row in cursor:
row[0].decode('utf-8')
def four(conn):
cursor = conn.cursor()
def conv_unicode(value):
return value.decode('utf-8')
cursor.execute("SELECT data FROM data")
for row in cursor:
conv_unicode(row[0])
import timeit
print "no unicode:", timeit.timeit("one(conn)", "from __main__ import conn, one", number=100)
print "native unicode:", timeit.timeit("two(conn)", "from __main__ import conn, two", number=100)
print "in Python unicode:", timeit.timeit("three(conn)", "from __main__ import conn, three", number=100)
print "more like SQLA's unicode:", timeit.timeit("four(conn)", "from __main__ import conn, four", number=100)
les horaires que je reçois:
no unicode: 2.10434007645
native unicode: 4.52875208855
in Python unicode: 4.77912807465
more like SQLA's unicode: 4.88325881958
donc ce qui est intéressant ici, est que l'approche de SQLA, si nous avons utilisé les extensions C, pourrait être un meilleur choix que l'approche native de psycopg2, si en fait vous n'utilisez pas beaucoup le type Unicode et la plupart de vos valeurs de chaînes sont seulement ASCII pur.
Réponse incroyable, merci!Par simple curiosité, quel type de machine utilisez-vous? Quand j'ai essayé votre script de test, je reçois ~ 30secs, bien que je sois dans une VM Ubuntu de 3gb. –