Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dlaczego ładowanie obiektów SQLAlchemy za pośrednictwem ORM 5-8x jest wolniejsze niż wierszy za pomocą surowego kursora MySQLdb?

Oto wersja SQLAlchemy twojego skryptu MySQL, która działa w cztery sekundy, w porównaniu do trzech dla MySQLdb:

from sqlalchemy import Integer, Column, create_engine, MetaData, Table
import datetime

metadata = MetaData()

foo = Table(
    'foo', metadata,
    Column('id', Integer, primary_key=True),
    Column('a', Integer(), nullable=False),
    Column('b', Integer(), nullable=False),
    Column('c', Integer(), nullable=False),
)


class Foo(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

engine = create_engine('mysql+mysqldb://scott:[email protected]/test', echo=True)
start = datetime.datetime.now()

with engine.connect() as conn:
    foos = [
        Foo(row['a'], row['b'], row['c'])
        for row in
        conn.execute(foo.select().limit(1000000)).fetchall()
    ]


print "total time: ", datetime.datetime.now() - start

czas działania:

total time:  0:00:04.706010

Oto skrypt, który używa ORM do pełnego załadowania wierszy obiektów; unikając tworzenia stałej listy ze wszystkimi 1 mln obiektów naraz przy użyciu wydajności na, działa to w 13 sekund z masterem SQLAlchemy (18 sekund z rel 0.9):

import time
from sqlalchemy import Integer, Column, create_engine, Table
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Foo(Base):
    __table__ = Table(
        'foo', Base.metadata,
        Column('id', Integer, primary_key=True),
        Column('a', Integer(), nullable=False),
        Column('b', Integer(), nullable=False),
        Column('c', Integer(), nullable=False),
    )


engine = create_engine('mysql+mysqldb://scott:[email protected]/test', echo=True)

sess = Session(engine)

now = time.time()

# avoid using all() so that we don't have the overhead of building
# a large list of full objects in memory
for obj in sess.query(Foo).yield_per(100).limit(1000000):
    pass

print("Total time: %d" % (time.time() - now))

Następnie możemy podzielić różnicę między tymi dwoma podejściami i załadować tylko pojedyncze kolumny za pomocą ORM:

for obj in sess.query(Foo.id, Foo.a, Foo.b, Foo.c).yield_per(100).limit(1000000):
    pass

Powyższe ponownie działa za 4 sekundy .

Porównanie SQLAlchemy Core jest trafniejszym porównaniem z surowym kursorem MySQLdb. Jeśli używasz ORM, ale zapytanie dotyczy poszczególnych kolumn, w najnowszych wersjach trwa to około czterech sekund.

Na poziomie ORM problemy z szybkością wynikają z tego, że tworzenie obiektów w Pythonie jest powolne, a SQLAlchemy ORM stosuje dużą ilość danych księgowych do tych obiektów podczas ich pobierania, co jest niezbędne do wypełnienia umowy użytkowania, w tym jednostki pracy, mapa tożsamości, chętne ładowanie, kolekcje itp.

Aby znacznie przyspieszyć zapytanie, pobieraj pojedyncze kolumny zamiast pełnych obiektów. Zobacz techniki nahttp://docs .sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm które to opisują.

Dla porównania z PeeWee, PW jest znacznie prostszym systemem z dużo mniejszą liczbą funkcji, w tym z tym, że nie robi nic z mapami tożsamości. Nawet z PeeWee, mniej więcej tak prostym ORM, jak to tylko możliwe, nadal zajmuje to 15 sekund , co jest dowodem na to, że cPython jest naprawdę wolny w porównaniu do surowego pobierania MySQLdb, który jest w prostym C.

W porównaniu z Javą, Java VM jest o wiele szybsza niż cPython . Hibernacja jest śmiesznie skomplikowane, ale Java VM jest niezwykle szybka dzięki JIT i nawet cała ta złożoność kończy się szybciej. Jeśli chcesz porównać Pythona z Javą, użyj Pypy.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mysql Max z Grupą według zapytania

  2. Zabij zapytanie MySQL przy przerwaniu użytkownika

  3. Wprowadzenie do wysokiej dostępności baz danych dla MySQL i MariaDB

  4. Windows:XAMPP vs WampServer vs EasyPHP vs alternatywa

  5. Mysql, przekształć dane z długich / wysokich na szerokie