我建立了两个模型,Message
和EmailAddress
通过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'))