如何建立SQLAlchemy关系以提高性能?

时间:2019-05-01 18:30:36

标签: python sqlalchemy flask-sqlalchemy

我建立了两个模型,MessageEmailAddress通过MessageEmailAddress表以多对多关系连接。 (我为Model使用了MessageEmailAddress类,因为存在与该关系相关联的元数据action。)这些relationships都是lazy=dynamic

运行实例方法Message.add_email_address()的速度非常慢,大约为1。每个对象1.5秒!!该方法需要检查是否存在预先存在的关系(即MessageEmailAddress中的行),如果不存在则创建新的关系。

如何在表之间建立更多性能关系?我的代码的哪个元素导致了这种缓慢的操作?

我尝试了许多其他方式来创建具有关联元数据的多对多关系-这是唯一不会引发错误的方式。

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()


class Message(db.Model):
    """A single message."""
    id = db.Column(db.Integer, primary_key=True)

    # Is there a way to dynamically create these?
    _email_addresses = relationship(
        "EmailAddress",
        secondary="message_email_address", lazy='dynamic', backref=backref("_messages", lazy='dynamic'))
    _email_addresses_from = relationship(
        "EmailAddress",
        primaryjoin="and_(Message.id==MessageEmailAddress.message_id, MessageEmailAddress.action=='from')",
        secondary="message_email_address",
        lazy='dynamic',
        backref=backref('_messages_from', lazy='dynamic')
    )
    _email_addresses_to = relationship(
        "EmailAddress",
        primaryjoin="and_(Message.id==MessageEmailAddress.message_id, MessageEmailAddress.action=='to')",
        secondary="message_email_address",
        lazy='dynamic',
        backref=backref('_messages_to', lazy='dynamic')
    )

    def add_email_address(self, email_str, action, name=None):
        """Setter method for all related EmailAddress objects.

        Args:
            email_str: A string, ex. "david@gmail.com"
            action: A string describing header action, ex. "from"
            name: Optional string for name of EmailAddress

        """
        # Ensure connection between Message, EmailAddress, and action is unique
        action_prop = '_email_addresses_' + action
        pre_existing = getattr(self, action_prop).filter_by(email_address=email_str).all()

        if pre_existing and len(pre_existing):
            return

        # Add new connection
        email_address = EmailAddress.get_or_create(
            email_address=email_str, create_kwargs=dict(name=name))
        a = MessageEmailAddress(message_id=self.id, email_id=email_address.id, action=action)
        db.session.add(a)
        db.session.commit()

        return email_address


class EmailAddress(db.Model, ModelMixin):
    """A single email address.

    Relationships to Message: _messages, _messages_from, _messages_to, etc.
    """
    id = db.Column(db.Integer, primary_key=True)
    ...


class MessageEmailAddress(db.Model):
    # Join Message and EmailAddress tables
    id = db.Column(db.Integer, primary_key=True)
    message_id = db.Column(
        db.Integer, db.ForeignKey('message.id'), nullable=False)
    email_id = db.Column(
        db.Integer, db.ForeignKey('email_address.id'), nullable=False)
    action = db.Column(db.String(), nullable=False)  # Ex. From, To, Bcc

    message = db.relationship("Message", backref=backref("message_email_address", lazy='dynamic'))
    email_address = db.relationship("EmailAddress", backref=backref("message_email_address", lazy='dynamic'))

0 个答案:

没有答案