Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Prisma2 with Graphql

B72422afc5f3ffc844f672b59122e16d?s=47 joe_re
August 28, 2020
610

Prisma2 with Graphql

GraphqlTokyo #10 LT 資料

B72422afc5f3ffc844f672b59122e16d?s=128

joe_re

August 28, 2020
Tweet

Transcript

  1. PRISMA2 WITH GRAPHQL @joe_re

  2. INTRODUCTION WHO AM I? ▸ twitter: @joe_re ▸ github: @joe-re

    ▸ GraphQL Tokyoのオーガナイザの1⼈です ▸ オンラインレッスン/ミーティングのサービスを作っています(@classdo) ▸ Prisma1は結構⻑く使ってきました (Graphcool時代から数えると2年半ぐらい)
  3. PRISMA1 AND PRISMA2 DIFFERENCE OF PRISMA1 AND PRISMA2 ▸ Prisma1はGraphQLのバックエンドサーバ(Prisma

    Server)を提供し、 http経由でDBのマイグレーションの指示や、GraphQLクエリとDBクエリの変 換、データの更新や取得を⾏う ▸ Prisma2ではPrisma Serverは撤廃され、アプリケーションコードから直接Prisma Engine(Rust製)というバイナリのAPIを叩いてデータの取得やマイグレーション を⾏う ▸ クライアントのAPIインターフェイスなどは受け継いでいるものの、 アーキテクチャからして全くの別物
  4. * Prisma2のプレビューのアナウンスメントブログより抜粋 https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5 PRISMA1 AND PRISMA2

  5. WHAT IS PRISMA2 OVERVIEW OF PRISMA2 ▸ Prisma2ではAPIサーバ側に直接DB接続を持つ ▸ イメージ的にはよりORMに近い動きになる

    (ただしPrismaは独⾃DSLに基づいたクライアントのオートジェネレーションや マイグレーションを提供することから⾃身のことをORMではなく database toolkitと位置づけしている)
  6. WHAT IS PRISMA2 OVERVIEW OF PRISMA2 アプリケーションサイド Prisma Client (旧Photon)

    クライアントのオートジェネレーションツール Prisma Migrate (旧Lift) 独⾃DSL(.prisma)に基づいたマイグレーション ツール Prisma CLI それぞれのツールの呼び出しのコマンドの提供 Prisma Studio データベースのビジュアルエディタ クエリエンジン Prisma Engine データベースへのクエリエンジン(Rust製) バイナリとして提供されて、アプリケーション サーバに配置される *Prismaの公式ドキュメント、Query Engineのページより抜粋 https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/query-engine
  7. WHAT IS PRISMA2 Q:あれ、GraphQL関係なくね? ▸ はい、ありません

  8. WHAT IS PRISMA2 ▸ Prisma2はPrisma1からクエリエンジンとクライアント(ORM)やマイグレーション やその周辺ツール部分をブラッシュアップしたプロダクト ▸ 基本的にGraphQLとのつながりはない (RestAPIサーバでもCLIツールでもなんで も使える)

    ▸ GraphQLの実装はNexusを使うことが推奨されている
  9. WHAT IS NEXUS WHAT IS NEXUS ▸ GraphQLのアプリケーションサーバを開発するTypeScriptのフレームワーク ▸ レポジトリはPrismaのオーガナイゼーション配下にはないけど、

    ドキュメントに何度も登場したりPrismaの開発者がコントリビュートしていたり ほぼ公式の位置づけ ▸ Schema-First開発をシンプルにして、その利便性とCode-First開発の保守性、 開発の素早さとを両⽴させることを⽬指している
  10. WHAT IS NEXUS DEVELOPMENT GRAPHQL SERVER ON NEXUS ▸ Code-Firstのアプローチで、先にResolverを記述する

    (graphql-jsの上で開発していて、⾒た⽬はSDLっぽくなる) ▸ Resolverの記述に伴い、開発サーバがリアルタイムにコードをビルドして、 GraphQLスキーマファイルとそれに対応した型ファイルの⽣成を⾏う ▸ 全てをリアルタイムにビルドする & 完全な型付けを提供することで、 ⼀般的なSchema-Firstにおける、GraphQLスキーマの記述 -> コードジェネレー ションの⼿間を省きつつその利点を得る
  11. WHAT IS NEXUS DEVELOPMENT GRAPHQL SERVER ON NEXUS api/Post.ts (Resolver)

    app.graphql node_modules/@type/typegen-nexus/index.d.ts 1. 先にResolverを記述 2. 開発サーバが変更を検知 3-1. GraphQLスキーマファイルの⽣成 3-2. Resolverの型ファイルを⽣成 (node_modules/@types以下に⽣成される)
  12. DEMO

  13. WHAT IS NEXUS THE IMPRESSION OF NEXUS ▸ ⼩さい範囲で試している範囲では快適な体験 ▸

    個⼈的にはSchema-First寄りの意⾒を持っていたけど、 このアプローチが上⼿くスケールするならあり (ただし今までPrismaは途中で開発をやめたプロダクトが少なからず あるので少し⼼配) ▸ プロダクトが⼤きくなった時のコードジェネレーションの速度が気になる
  14. 時間があればちょっとだけ クエリオプティマイズの話をします

  15. GraphQLでN+1起きがち問題ありますよね??

  16. こんなの ユーザ全件を取得するクエリ定義 ユーザのタイプ定義 (Type Resolver) ユーザ1件に対して1件のProfileを取得する

  17. PRISMA1ではどう解決されていたか ▸ Prisma1ではPrisma Serverへ⾶ぶリクエストがまとめられて、⼀気にサーバ側で 解決される https://github.com/prisma-labs/http-link-dataloader ▸ ⼀⾒N+1が起きそうなコードを書いても、 ある程度のところまでは⾃動でオプティマイズされる (

    深刻なパフォーマンスの問題が出ればもちろん真剣に取り組む必要はある) ▸ Prisma1からPrisma2へ移⾏を考える上で検証は避けては通れないところ
  18. 試してみた

  19. 結果 ▸ 1 つ⽬: ユーザ全体を取得する(params: [-1, 0]) SELECT `dev`.`User`.`id`, `dev`.`User`.`email`,

    `dev`.`User`.`name` FROM `dev`.`User` WHERE 1=1 LIMIT ? OFFSET ? ▸ 2つ⽬-4つ⽬: ユーザ単位でポストの全体を取得する (params: [userId, -1, 0]) SELECT `dev`.`Post`.`id`, `dev`.`Post`.`authorId`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`title` FROM `dev`.`Post` WHERE (`dev`.`Post`.`id`) IN (SELECT `t0`.`id` FROM `dev`.`Post` AS `t0` INNER JOIN `dev`.`User` AS `j0` ON (`j0`.`id`) = (`t0`.`authorId`) WHERE `j0`.`id` = ?) LIMIT ? OFFSET ? ▸ 5つ⽬: Profile取得対象のユーザの存在を確かめる(?) (params: [1, 2, 3, -1, 0]) SELECT `dev`.`User`.`id` FROM `dev`.`User` WHERE `dev`.`User`.`id` IN (?,?,?) LIMIT ? OFFSET ? ▸ 6つ⽬: Profileの取得(params: [1, 2, 3, -1, 0]) SELECT `dev`.`Profile`.`id`, `dev`.`Profile`.`bio`, `dev`.`Profile`.`userId` FROM `dev`.`Profile` WHERE `dev`.`Profile`.`userId` IN (?,?,?) LIMIT ? OFFSET ? まとめられてる!
  20. 気になったのでコードを追ってみたところ、現状はfindOneのクエリはまとめられるようです ▸ Client側のリクエストのバッチ送信処理 https://github.com/prisma/prisma/blob/2.5.1/src/packages/client/src/runtime/Dataloader.ts#L31 ▸ クエリエンジン側のオプティマイゼーションの判定処理 (同じファイルにオプティマイゼーションの処理も ある) https://github.com/prisma/prisma-engines/blob/2.6.0-dev.44/query-engine/core/src/query_document/ mod.rs#L61

    ▸ GraphQLのResolverで最もN+1が起きやすいコードはこれだと思うので、ここがオプティマイズされるのは 嬉しい ▸ オプティマイズ効かせるのに少しコツがいりそうなので、このあたりもドキュメントになって欲しい気持ち
  21. THANK YOU!