Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Mengapa memuat objek SQLAlchemy melalui ORM 5-8x lebih lambat daripada baris melalui kursor MySQLdb mentah?

Berikut adalah versi SQLAlchemy dari skrip MySQL Anda yang bekerja dalam empat detik, dibandingkan dengan tiga detik untuk 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

waktu proses:

total time:  0:00:04.706010

Berikut adalah skrip yang menggunakan ORM untuk memuat baris objek sepenuhnya; dengan menghindari pembuatan daftar tetap dengan semua 1 juta objek sekaligus menggunakan hasil per, ini berjalan dalam 13 detik dengan SQLAlchemy master (18 detik dengan 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))

Kami kemudian dapat membagi perbedaan antara dua pendekatan ini, dan memuat kolom individual saja dengan ORM:

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

Di atas kembali berjalan dalam 4 detik .

Perbandingan SQLAlchemy Core adalah perbandingan yang lebih tepat dengan kursor MySQLdb mentah. Jika Anda menggunakan ORM tetapi melakukan kueri untuk masing-masing kolom, itu sekitar empat detik di versi terbaru.

Pada tingkat ORM, masalah kecepatan adalah karena pembuatan objek dengan Python lambat, dan SQLAlchemy ORM menerapkan sejumlah besar pembukuan ke objek ini saat mengambilnya, yang diperlukan untuk memenuhi kontrak penggunaannya, termasuk unit pekerjaan, peta identitas, pemuatan yang bersemangat, koleksi, dll.

Untuk mempercepat kueri secara dramatis, ambil kolom individual alih-alih objek penuh. Lihat tekniknya dihttp://docs .sqlalchemy.org/en/latest/faq/performance.html#result-fetching-slowness-orm yang menggambarkan ini.

Sebagai perbandingan Anda dengan PeeWee, PW adalah sistem yang jauh lebih sederhana dengan fitur yang jauh lebih sedikit, termasuk tidak melakukan apa pun dengan peta identitas. Bahkan dengan PeeWee, ORM sesederhana mungkin, masih membutuhkan waktu 15 detik , yang merupakan bukti bahwa cPython sangat lambat dibandingkan dengan pengambilan MySQLdb mentah yang ada di C.

Sebagai perbandingan dengan Java, Java VM jauh lebih cepat daripada cPython . Hibernasi konyolnya rumit, namun Java VM sangat cepat karena JIT dan bahkan semua kerumitan itu akhirnya berjalan lebih cepat. Jika Anda ingin membandingkan Python dengan Java, gunakan 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 bergabung dengan kueri menggunakan suka?

  2. versi php-mysql bertentangan dengan server Mysql

  3. Menghitung Median dengan Mysql

  4. doktrin2 - Bagaimana cara meningkatkan efisiensi flush?

  5. Masalah koneksi Ruby on Rails