Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Prisma2 with Graphql
joe_re
August 28, 2020
3
760
Prisma2 with Graphql
GraphqlTokyo #10 LT 資料
joe_re
August 28, 2020
Tweet
Share
More Decks by joe_re
See All by joe_re
Go beyound static on Netlify
joere
1
160
Building Real-time Vue App
joere
4
3.9k
ReactNativeのAsyncStorageをNodeのReplから操作する
joere
0
200
Mock Native API in your E2E test
joere
2
870
Data feching and caching on Apollo Client
joere
2
2.2k
Typed Vuex Data Flow
joere
0
440
AsyncStorageをNodeのREPLから操作するためにTop-levelでawaitしたい人生だった
joere
0
400
Our choice in ReactNative
joere
8
8.3k
Effective E2E Test In An Electron Application
joere
1
690
Featured
See All Featured
Pencils Down: Stop Designing & Start Developing
hursman
112
9.8k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
11
4.6k
Happy Clients
brianwarren
89
5.5k
4 Signs Your Business is Dying
shpigford
169
20k
Rails Girls Zürich Keynote
gr2m
86
12k
Making the Leap to Tech Lead
cromwellryan
113
6.9k
Building Your Own Lightsaber
phodgson
94
4.6k
It's Worth the Effort
3n
172
25k
Put a Button on it: Removing Barriers to Going Fast.
kastner
56
2.3k
We Have a Design System, Now What?
morganepeng
35
2.9k
KATA
mclloyd
7
8.6k
WebSockets: Embracing the real-time Web
robhawkes
57
5k
Transcript
PRISMA2 WITH GRAPHQL @joe_re
INTRODUCTION WHO AM I? ▸ twitter: @joe_re ▸ github: @joe-re
▸ GraphQL Tokyoのオーガナイザの1⼈です ▸ オンラインレッスン/ミーティングのサービスを作っています(@classdo) ▸ Prisma1は結構⻑く使ってきました (Graphcool時代から数えると2年半ぐらい)
PRISMA1 AND PRISMA2 DIFFERENCE OF PRISMA1 AND PRISMA2 ▸ Prisma1はGraphQLのバックエンドサーバ(Prisma
Server)を提供し、 http経由でDBのマイグレーションの指示や、GraphQLクエリとDBクエリの変 換、データの更新や取得を⾏う ▸ Prisma2ではPrisma Serverは撤廃され、アプリケーションコードから直接Prisma Engine(Rust製)というバイナリのAPIを叩いてデータの取得やマイグレーション を⾏う ▸ クライアントのAPIインターフェイスなどは受け継いでいるものの、 アーキテクチャからして全くの別物
* Prisma2のプレビューのアナウンスメントブログより抜粋 https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5 PRISMA1 AND PRISMA2
WHAT IS PRISMA2 OVERVIEW OF PRISMA2 ▸ Prisma2ではAPIサーバ側に直接DB接続を持つ ▸ イメージ的にはよりORMに近い動きになる
(ただしPrismaは独⾃DSLに基づいたクライアントのオートジェネレーションや マイグレーションを提供することから⾃身のことをORMではなく database toolkitと位置づけしている)
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
WHAT IS PRISMA2 Q:あれ、GraphQL関係なくね? ▸ はい、ありません
WHAT IS PRISMA2 ▸ Prisma2はPrisma1からクエリエンジンとクライアント(ORM)やマイグレーション やその周辺ツール部分をブラッシュアップしたプロダクト ▸ 基本的にGraphQLとのつながりはない (RestAPIサーバでもCLIツールでもなんで も使える)
▸ GraphQLの実装はNexusを使うことが推奨されている
WHAT IS NEXUS WHAT IS NEXUS ▸ GraphQLのアプリケーションサーバを開発するTypeScriptのフレームワーク ▸ レポジトリはPrismaのオーガナイゼーション配下にはないけど、
ドキュメントに何度も登場したりPrismaの開発者がコントリビュートしていたり ほぼ公式の位置づけ ▸ Schema-First開発をシンプルにして、その利便性とCode-First開発の保守性、 開発の素早さとを両⽴させることを⽬指している
WHAT IS NEXUS DEVELOPMENT GRAPHQL SERVER ON NEXUS ▸ Code-Firstのアプローチで、先にResolverを記述する
(graphql-jsの上で開発していて、⾒た⽬はSDLっぽくなる) ▸ Resolverの記述に伴い、開発サーバがリアルタイムにコードをビルドして、 GraphQLスキーマファイルとそれに対応した型ファイルの⽣成を⾏う ▸ 全てをリアルタイムにビルドする & 完全な型付けを提供することで、 ⼀般的なSchema-Firstにおける、GraphQLスキーマの記述 -> コードジェネレー ションの⼿間を省きつつその利点を得る
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以下に⽣成される)
DEMO
WHAT IS NEXUS THE IMPRESSION OF NEXUS ▸ ⼩さい範囲で試している範囲では快適な体験 ▸
個⼈的にはSchema-First寄りの意⾒を持っていたけど、 このアプローチが上⼿くスケールするならあり (ただし今までPrismaは途中で開発をやめたプロダクトが少なからず あるので少し⼼配) ▸ プロダクトが⼤きくなった時のコードジェネレーションの速度が気になる
時間があればちょっとだけ クエリオプティマイズの話をします
GraphQLでN+1起きがち問題ありますよね??
こんなの ユーザ全件を取得するクエリ定義 ユーザのタイプ定義 (Type Resolver) ユーザ1件に対して1件のProfileを取得する
PRISMA1ではどう解決されていたか ▸ Prisma1ではPrisma Serverへ⾶ぶリクエストがまとめられて、⼀気にサーバ側で 解決される https://github.com/prisma-labs/http-link-dataloader ▸ ⼀⾒N+1が起きそうなコードを書いても、 ある程度のところまでは⾃動でオプティマイズされる (
深刻なパフォーマンスの問題が出ればもちろん真剣に取り組む必要はある) ▸ Prisma1からPrisma2へ移⾏を考える上で検証は避けては通れないところ
試してみた
結果 ▸ 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 ? まとめられてる!
気になったのでコードを追ってみたところ、現状は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が起きやすいコードはこれだと思うので、ここがオプティマイズされるのは 嬉しい ▸ オプティマイズ効かせるのに少しコツがいりそうなので、このあたりもドキュメントになって欲しい気持ち
THANK YOU!