The attached script generates an inefficient query at the end:
SELECT `People`.friday_id AS `People_friday_id`, `People`.parent_id AS
`People_parent_id`, `People`.user_hash AS `People_user_hash`
FROM `People`
WHERE `People`.friday_id = %s AND `People`.user_hash = `People`.user_hash
Please note the user_hash = user_hash clause being generated there. This
query takes a heavy toll on the datastore and has become a huge bottleneck
in our application.
This is the core ORM configuration:
class User(Base):
hash = Column(String(64), primary_key=True)
class UserMixin(object):
@declared_attr
def user_hash(cls):
return Column(String(64), ForeignKey('User.hash'), primary_key=True)
class People(UserMixin, Base):
friday_id = Column(BigInteger, primary_key=True, nullable=False,
autoincrement=False)
# This line mysteriously fixes the query
#user_hash = Column(String(64), ForeignKey('User.hash'),
# primary_key=True)
parent_id = Column(BigInteger)
@declared_attr
def parent(cls):
return relationship(
'People', remote_side=[cls.friday_id, cls.user_hash],
post_update=True)
__table_args__ = (
ForeignKeyConstraint(
['parent_id', 'user_hash'],
['People.friday_id', 'People.user_hash'],
ondelete='CASCADE'),)
As shown in the comments, if I remove the UserMixin, the query becomes sane.
--
Fayaz Yusuf Khan
Cloud architect, Dexetra SS, India
fayaz.yusuf.khan_AT_gmail_DOT_com, fayaz_AT_dexetra_DOT_com
+91-9746-830-823
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker, backref, relationship
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base, declared_attr
class TableNameMixin(object):
@declared_attr
def __tablename__(cls):
return cls.__name__
Base = declarative_base(cls=TableNameMixin)
class User(Base):
hash = Column(String(64), primary_key=True)
class UserMixin(object):
@declared_attr
def user_hash(cls):
return Column(String(64), ForeignKey('User.hash'), primary_key=True)
class People(UserMixin, Base):
friday_id = Column(BigInteger, primary_key=True, nullable=False,
autoincrement=False)
# This line mysteriously fixes the query
#user_hash = Column(String(64), ForeignKey('User.hash'), primary_key=True)
parent_id = Column(BigInteger)
@declared_attr
def parent(cls):
return relationship(
'People', remote_side=[cls.friday_id, cls.user_hash],
post_update=True)
__table_args__ = (
ForeignKeyConstraint(
['parent_id', 'user_hash'],
['People.friday_id', 'People.user_hash'],
ondelete='CASCADE'),)
engine = create_engine('mysql://root@localhost', echo=True)
engine.execute('CREATE DATABASE test')
engine.execute('USE test')
Session = sessionmaker()
Session.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all()
session = Session()
hash_string = '0' * 64
session.add(User(hash=hash_string))
session.flush()
session.add(People(user_hash='0'*64, friday_id=1, parent_id=1))
session.add(People(user_hash='0'*64, friday_id=2, parent_id=1))
people = session.query(People).filter_by(friday_id=2).one()
print "After query"
print people.parent
engine.execute('DROP DATABASE test')