什么时候用 joinedload,什么时候用 selectinload?一对多为什么必须 unique()?嵌套多层时哪个更划算?这篇在真实的 PostgreSQL 上把两者的 SQL、行数、耗时和分块行为逐项量出来。
joinedload + limit(5):
SELECT anon_1.id, anon_1.name, anon_1.bio, book_1.id AS id_1, book_1.title, book_1.author_id FROM (SELECT author.id AS id, author.name AS name, author.bio AS bio FROM author LIMIT %(param_1)s::INTEGER) AS anon_
selectinload + limit(5):
SELECT author.id, author.name, author.bio FROM author LIMIT %(param_1)s::INTEGER
SELECT book.author_id, book.id, book.title FROM book WHERE book.author_id IN (%(primary_keys_1)s::INTEGER, %(primary_keys_2)s::INTEGER, %(primary_keys_3)s::INTEGER, %(primary_keys_4)s::INTEGER, %(primary_keys_5上一篇:Lazy Loading 与 Eager Loading;下一篇:N+1 查询问题。
InvalidRequestError: The unique() method must be invoked on this Result, as it contains results that include joined eager loads aga
不预加载(lazy,N+1) 47.7 ms SQL 301 条 作者 300 本书 3000 joinedload 21.7 ms SQL 1 条 作者 300 本书 3000 selectinload 10.5 ms SQL 2 条 作者 300 本书 3000 JOIN 的结果集行数:3000(作者的 bio 在每一行里都重复一遍),selectin 的两条查询分别返回 300 与 3000 行
数据库在本机、关了 fsync,所以只看相对关系,不看绝对值。
joinedload 链 100.3 ms SQL 1 条 selectinload 链 63.3 ms SQL 8 条 joinedload 链返回的行数 = 9000 (作者 × 书 × 评论 的乘积)
joinedload(Book.author) 11.5 ms SQL 1 条/次 书 1500 selectinload(Book.author) 8.3 ms SQL 2 条/次 书 1500
300 个作者:2 条 SQL
600 个作者:3 条 SQL
1200 个作者:4 条 SQL