Build a CRUD App with SQLAlchemy - Configuring Relationships

db.relationship: Allows you to configure when joined assets should be loaded.

When calling child1.some_parent, SQLAlchemy determines when we load the parent from the database.

Why is it important to care about when we load parents?

  • Joins are expensive
  • We should avoid having the user idling. Deplays more 150ms are noticeable, so milliseconds of performance matter!
  • We should make sure the joins happen during a time and place in the UX that doesn’t negatively impact the experience too much.

Lazy loading
Load needed joined data only as needed. Default in SQLAlchemy.

  • Pro: no initial wait time. Load only what you need.
  • Con: produces a join SQL call every time there is a request for a joined asset. Bad if you do this a lot.
lazy='select'
(same as lazy=True)

Eager loading
Load all needed joined data objects, all at once.

  • Pro: reduces further queries to the database. Subsequent SQL calls read existing data
  • Con: loading the joined table has a long upfront initial load time.
lazy='joined'

lazy=True (lazy loading) is the default option in db.relationship:

children = db.relationship('ChildModel', backref='some_parent', lazy=True)

class SomeParent(db.Model):
	id = db.Column(db.Integer, primary_key=True)
	name = db.Column(db.String(50), nullable=False)
	# SomeChild: Name of the child class (passed as a string)
	# some_parent: Custome property name of what to call the parent on a child
	# Lazy: Configure lazy or eager loading options
	children = db.relationship('SomeChild', backref='some_parent', lazy=True)

The loading of relationships falls into three categories:

  • Lazy loading
  • Eager loading
  • No loading

Lazy loading refers to objects are returned from a query without the related objects loaded at first. When the given collection or reference is first accessed on a particular object, an additional SELECT statement is emitted such that the requested collection is loaded.

Eager loading refers to objects returned from a query with the related collection or scalar reference already loaded up front. The Query achieves this either by augmenting the SELECT statement it would normally emit with a JOIN to load in related rows simultaneously, or by emitting additional SELECT statements after the primary one to load collections or scalar references at once.

No loading refers to the disabling of loading on a given relationship, either that the attribute is empty and is just never loaded, or that it raises an error when it is accessed, in order to guard against unwanted lazy loads.

SQLAlchemy Docs on Relationship Options


class Parent(db.Model):
	__tablename__ = 'parents'
	id = db.Column(db.Integer, primary_key=True)
	name = db.Column(db.String(), nullable=False)
	children = db.relationship(
		'Child',
		backref = 'parent',
		lazy = True,
		collection_class = list,
		cascade = 'save-update'  # OR: all, delete-orphan

db.relationship:

  • Allows SQLAlchemy to identify relationships between models
  • Links relationships with backrefs(child1.some_parent)
  • Configures relationship dynamics between parents and children, including options like lazy, collection_class, and cascade

Lazy Loading:

  • Loading joined data only as needed
  • lazy = True
  • lazy = ‘select’
  • No initial wait time
  • Producing a joined SQL call on every request

Eager Loading:

  • Loading all possible joined data at once
  • Large upfront initial load time
  • Allowing subsequent SQL calls to read from existing data

猜你喜欢

转载自blog.csdn.net/BSCHN123/article/details/121558588