2

私は declarative_base() を使用しており、多対多の関係を使用するときに遅延内部結合を強制する方法を見つけようとしています。

MySQL と InnoDB に外部キー制約が定義されたテーブルがあります。

users: userid, name
permissions: permissionid, name
users_permissions: userid, permissionid

metadata.reflect()データベースをロードするために使用しています。


class User_Perm(Base):
    __table__ = Base.metadata.tables['users_permissions']

class User(Base):
    __table__ = Base.metadata.tables['users']

    permissions = orm.relationship('Permission',
            secondary=User_Perm.__table__,
            order_by='Perm.name',
            innerjoin=True,
            lazy=True,
            )

class Permission(Base):
    __table__ = Base.metadata.tables['permissions']

私が選択するたびに

u = Session().query(User).filter(User.name == 'myuser').first()
u.permissions

MySQL サーバーが受け取るクエリは次のとおりです。

SELECT permissions.permissionid AS permissions_permissionid,
     permissions.name AS permissions_name
FROM permissions, users_permissions 
WHERE ? = users_permissions.userid
    AND permissions.permissionid = users_permissions.permissionid
ORDER BY permissions.name

ご覧のとおり、これはFROM permissions, users_permissions内部結合ではありません。使用せずにこれを強制できますかlazy=False。そうすると、カスケード効果によりpermissions、別のテーブルとの関係もあり (例には記載されていません)、users他のテーブルにも関連している (ここでも、そうではありません) ため、あまりにも多くの情報が読み込まれます。例に記載されています)。すべてのクラスのリレーションシップに同じテンプレートを使用したいと考えています。

編集:コンテキスト現在のシステムの SQL クエリと一致するように、すべての SQL クエリを複製しようとしています。oursqlからに移行しようとしていsqlalchemy ormます。

4

1 に答える 1

4

MySQL内部結合を行っています。つまり、表示されたクエリは内部結合の 1 つの実装です。

ドキュメントから:

innerjoin=False – True の場合、結合された熱心なロードは、外部結合の代わりに内部結合を使用して関連するテーブルに対して結合します。通常、内部結合は外部結合よりもパフォーマンスが優れているため、このオプションの目的は厳密にはパフォーマンスの 1 つです。このフラグは、リレーションシップが、NULL 許容ではないローカル外部キーを使用して多対 1 でオブジェクトを参照する場合、または参照が 1 対 1 または 1 つまたは少なくとも 1 つを持つことが保証されているコレクションである場合に、True に設定できます。 1 つのエントリ。

重要なポイントは、内部結合と外部結合です。構文は無関係です。

inner joinクエリは、まったく同じ意味を持つ構文形式を使用してクエリに変換できることに注意してください。

SELECT permissions.permissionid AS permissions_permissionid,
     permissions.name AS permissions_name
FROM permissions
INNER JOIN users_permissions 
    ON permissions.permissionid = users_permissions.permissionid
WHERE ? = users_permissions.userid
ORDER BY permissions.name

MySQL は通常、2 つの形式に対して同一の実行計画を生成します。

于 2012-05-03T19:31:56.913 に答える