2015-05-19 18 views
8

Tôi đang sử dụng Flask-SQLAlchemy để thực hiện chèn hàng loạt lớn 60 nghìn hàng. Tôi cũng có mối quan hệ nhiều-nhiều trên bảng này, vì vậy tôi không thể sử dụng db.engine.execute cho điều này. Trước khi chèn, tôi cần phải tìm các mục tương tự trong cơ sở dữ liệu và thay đổi chèn vào bản cập nhật nếu tìm thấy một mục trùng lặp.Chèn số lượng lớn với Flask-SQLAlchemy

Tôi có thể thực hiện việc kiểm tra này trước và sau đó thực hiện chèn hàng loạt qua db.engine.execute, nhưng tôi cần khóa chính của hàng khi chèn.

Hiện tại, tôi đang thực hiện một số db.session.add()db.session.commit() trên mỗi lần chèn và tôi nhận được 3-4 lần chèn mỗi giây.

Tôi đã chạy hồ sơ để xem nút cổ chai ở đâu và có vẻ như là db.session.commit() đang chiếm 60% thời gian.

Có cách nào cho phép tôi thực hiện thao tác này nhanh hơn, có lẽ bằng cách nhóm các cam kết, nhưng điều đó sẽ cho tôi các khóa chính trở lại?

Đây là những gì mô hình của tôi trông giống như:

class Item(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(1024), nullable=True) 
    created = db.Column(db.DateTime()) 
    tags_relationship = db.relationship('Tag', secondary=tags, backref=db.backref('items', lazy='dynamic')) 
    tags = association_proxy('tags_relationship', 'text') 

class Tag(db.Model): 
id = db.Column(db.Integer, primary_key=True) 
text = db.Column(db.String(255)) 

hoạt động chèn của tôi là chạy như thế này:

for item in items: 
    if duplicate: 
     update_existing_item 
    else: 
     x = Item() 
     x.title = "string" 
     x.created = datetime.datetime.utcnow() 
     for tag in tags: 
      if not tag_already_exists: 
       y = Tag() 
       y.text = "tagtext" 
       x.tags_relationship.append(y) 
       db.session.add(y) 
       db.session.commit() 
      else: 
       x.tags_relationship.append(existing_tag) 
    db.session.add(x) 
    db.session.commit() 

Trả lời

2

Có lẽ bạn nên cố gắng db.session.flush() để gửi dữ liệu đến máy chủ, có nghĩa là bất kỳ khóa chính nào sẽ được tạo. Cuối cùng, bạn có thể db.session.commit() thực sự thực hiện giao dịch.

+0

Thay đổi 'db.session.commit()' thành 'db.session.flush()' và sau đó thực hiện 'db.session.commit()' ở cuối tôi 10-12 chèn mỗi giây, nhanh hơn chắc chắn, nhưng không nhiều. –

0

Tôi sử dụng mã sau để đọc nhanh nội dung của khung dữ liệu gấu trúc vào SQLite. Lưu ý rằng nó phá vỡ các tính năng ORM của SQLAlchemy. myClass trong ngữ cảnh này là một lớp dẫn xuất db.Model có một tablename được gán cho nó. Khi các đoạn mã đề cập đến, tôi đã điều chỉnh

l = df.to_dict('records') 
# bulk save the dictionaries, circumventing the slow ORM interface 
# c.f. https://gist.github.com/shrayasr/5df96d5bc287f3a2faa4 
connection.engine.execute(
    myClass.__table__.insert(), 
    l 
) 
Các vấn đề liên quan