Skip to content

refactor(author): count poems with left join and group by#66

Merged
palemoky merged 1 commit into
palemoky:mainfrom
hawk-roy:for_author_pref
Jul 15, 2026
Merged

refactor(author): count poems with left join and group by#66
palemoky merged 1 commit into
palemoky:mainfrom
hawk-roy:for_author_pref

Conversation

@hawk-roy

Copy link
Copy Markdown
Contributor

Summary

This PR optimizes GetAuthorsWithStats by changing how poem_count is calculated for authors.

Previously, the query used a correlated subquery to count poems for each author row. That means the database may need to evaluate the count repeatedly as the author result set grows.

This change replaces it with a LEFT JOIN plus GROUP BY, so poem counts are calculated through one aggregate query while preserving the existing API behavior.

Why This Change

The previous approach was simple, but it could become inefficient on larger datasets because the poem count was calculated separately for each author.

Using LEFT JOIN and GROUP BY lets the database compute poem counts in a more set-oriented way. This is generally easier for the query optimizer to handle, especially when poems.author_id is indexed.

What Changed

  • Replaced the per-author correlated subquery with a join-based aggregate query.
  • Used COUNT(poems.id) to calculate each author's poem count.
  • Used LEFT JOIN so authors without poems are still included.
  • Added GROUP BY authors.id to aggregate poem counts by author.

Behavior Preserved

  • Authors are still ordered by poem_count DESC.
  • Pagination with limit and offset is unchanged.
  • Dynasty loading logic is unchanged.
  • The API response shape remains the same.

Testing

Tested locally and confirmed the author stats API still returns the expected results.

@palemoky
palemoky self-requested a review July 15, 2026 00:06
@codecov-commenter

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@palemoky palemoky self-assigned this Jul 15, 2026
@palemoky

Copy link
Copy Markdown
Owner

感谢 PR!先说结论:改动前后的查询完全一致,但在性能上略微下降,为了提高维护性与风格一致性,可以合并。

以下是我的测试结果:

测试环境:

  • 设备:Mac mini M4 16GB
  • OS:macOS 27 Beta 3
  • SQLite:3.54.0
  • 数据库:poetry.db v0.6.0
  • 测试数据:authors_zh_hans = 13,577poems_zh_hans = 371,313

测试结果:

查询方式 子查询 连表查询
单次耗时 ~8.4 ms ~14.8 ms(约慢 1.75×)

为什么更慢?

  • 子查询:每位作者用 author_id 覆盖索引做一次 count,只是一段范围扫描,非常便宜;最后仅对 ~1.3 万行作者排序。
  • 连表查询:LEFT JOIN 会先展开出约 37 万行(每首诗一行),再 GROUP BY 聚合回 1.3 万行并排序。多处理 37 万行的开销c超过了"单次聚合"的收益

另外,由于有 ORDER BY poem_count DESC + LIMIT,两种写法都必须先算出所有作者的计数才能排序分页,谁都无法提前截断,所以 join 并没有省下计算量。

@palemoky palemoky changed the title perf(author): count poems with left join and group by refactor(author): count poems with left join and group by Jul 15, 2026

@palemoky palemoky left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

虽然性能有所下降,但未来数据几乎不会增长,为了保持代码风格一致性与可维护性,准许合并。

@palemoky
palemoky merged commit 1c182df into palemoky:main Jul 15, 2026
1 check passed
@hawk-roy

Copy link
Copy Markdown
Contributor Author

感谢您的合并和快速反馈!您补充的子查询与 JOIN 查询的实际执行结果对我很有帮助,也让我更清楚这个改动在当前数据规模下的性能影响。有点酷!

@hawk-roy
hawk-roy deleted the for_author_pref branch July 15, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants