Skip to content

Commit 7a5eac9

Browse files
authored
feat: add optimize example apps (#DA-1251) (#6601)
* feat: add optimize example apps * feat: add Optimize examples to the read me * Update optimize/optimize-full-table-scan/package.json * feat: add .env.example files * Update optimize/optimize-full-table-scan/package.json * Update optimize/optimize-excessive-rows/package.json * Update optimize/optimize-unindexed-column/utils/db.ts * Update optimize/optimize-full-table-scan/utils/db.ts * Update optimize/optimize-excessive-rows/utils/db.ts * Update optimize/optimize-unindexed-column/package.json
1 parent cfddac5 commit 7a5eac9

38 files changed

+864
-0
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,16 @@ The [`pulse`](./pulse) folder contains examples of projects using [Prisma Pulse]
6464
| [`product-search-with-typesense`](./pulse/product-search-with-typesense) | A cron job that syncs data into Typesense (built with Hono.js) |
6565
| [`data-sync-with-bigquery`](./pulse/data-sync-with-bigquery) | A script that automatically syncs data into Google BigQuery |
6666

67+
## Prisma Optimize
6768

69+
The [`optimize`](./optimize) folder contains examples of projects using [Prisma Optimize](https://www.prisma.io/data-platform/optimize) to identify and improve the performance of slow queries.
70+
71+
| Demo | Description |
72+
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
73+
| [`starter`](./optimize/starter) | A Prisma Optimize starter app |
74+
| [`optimize-excessive-rows`](./optimize/optimize-excessive-rows) | An example app demonstrating the "Excessive number of rows returned" recommendation provided by Optimize. |
75+
| [`optimize-full-table-scan`](./optimize/optimize-full-table-scan) | An example app demonstrating the "Full table scans caused by `LIKE` operations" recommendation provided by Optimize. |
76+
| [`optimize-unindexed-column`](./optimize/optimize-unindexed-column) | An example app demonstrating the "Query filtering on an unindexed column" recommendation provided by Optimize. |
6877

6978
## Prisma ORM (TypeScript)
7079

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DATABASE_URL=""
2+
OPTIMIZE_API_KEY=""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
*.env
4+
package-lock.json
5+
prisma/migrations
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Prisma Optimize Usage Example: Applying the "Excessive number of rows returned" Recommendation
2+
3+
This repository demonstrates how to use [Prisma Optimize](https://pris.ly/optimize) to improve query performance using the "Excessive number of rows returned" recommendation.
4+
5+
## Prerequisites
6+
7+
To successfully run the project, you will need the following:
8+
9+
1. A **database connection string** supported by Prisma Optimize.
10+
2. An Optimize API key, which you can obtain from your [Prisma Data Platform](https://pris.ly/pdp) account.
11+
12+
## Getting started
13+
14+
### 1. Clone the repository
15+
16+
Clone the repository, navigate into it, and install the dependencies:
17+
18+
```bash
19+
git clone [email protected]:prisma/prisma-examples.git --depth=1
20+
cd prisma-examples/optimize/optimize-excessive-rows
21+
npm install
22+
```
23+
24+
### 2. Configure environment variables
25+
26+
Create a `.env` file in the root of the project directory:
27+
28+
```bash
29+
cp .env.example .env
30+
```
31+
32+
Next, open the `.env` file and update the `DATABASE_URL` with your database connection string and the `OPTIMIZE_API_KEY` with your Optimize API key:
33+
34+
```env
35+
# .env
36+
DATABASE_URL="__YOUR_DATABASE_CONNECTION_STRING__"
37+
# Replace __YOUR_DATABASE_CONNECTION_STRING__ with your actual connection string.
38+
OPTIMIZE_API_KEY="your_secure_optimize_api_key"
39+
```
40+
41+
- `DATABASE_URL`: The connection string to your database.
42+
- `OPTIMIZE_API_KEY`: Reference the [Environment API Keys](https://www.prisma.io/docs/platform/about#environment) section in our documentation to learn how to obtain an API key for your project using Optimize.
43+
44+
### 3. Set up the project
45+
46+
Perform a database migration to prepare the project:
47+
48+
```bash
49+
npx prisma migrate dev --name init
50+
```
51+
52+
### 4. Open the Optimize dashboard
53+
54+
You can create [recordings](https://pris.ly/optimize-recordings) and view detailed insights into your queries, along with optimization [recommendations](https://pris.ly/optimize-recommendations), in the Optimize dashboard. To access the dashboard:
55+
56+
1. Log in to your [Prisma Data Platform](https://console.prisma.io/optimize) account. If you haven't already, complete the onboarding process for Optimize by clicking the **Get Started** button.
57+
2. If Optimize hasn't been launched yet, click the **Launch Optimize** button.
58+
3. If you want to use a different workspace, navigate to your desired [Workspace](https://www.prisma.io/docs/platform/about#workspace), click the **Optimize** tab on the left sidebar to open the Optimize dashboard. Then, if Optimize is not yet launched, click the **Launch Optimize** button.
59+
60+
### 5. Run the script
61+
62+
Let's run the [script with unoptimized Prisma queries](./script.ts):
63+
64+
1. In the Optimize dashboard, click the **Start new recording** button.
65+
2. In the project terminal, run the project with:
66+
67+
```bash
68+
npm run dev
69+
```
70+
71+
3. After the script completes, you'll see a log saying "Done." Then, in the Optimize dashboard, click the **Stop recording** button.
72+
4. Observe the queries with high latencies highlighted in red, and review the recommendations in the **Recommendations** tab. You should see the recommendation:
73+
- **Excessive number of rows returned**
74+
> For more insights on this recommendation, click the **Ask AI** button and interact with the [AI Explainer](https://pris.ly/optimize-ai-chatbot) chatbot.
75+
5. To create a reference for comparison with other recordings, rename the recording to _Unoptimized queries_ by clicking the green recording label chip in the top left corner and typing "Unoptimized queries".
76+
77+
![Rename recording](./images/edit-recording-name-chip.png)
78+
79+
### Optimize example: applying the "Excessive number of rows returned" recommendation
80+
81+
Next, let’s follow the recommendation provided by Optimize to improve the performance of the queries:
82+
83+
1. To improve the performance of [**Query 1**](./script.ts) by addressing the [**Excessive number of rows returned**](https://pris.ly/optimize/r/excessive-rows) recommendation, add a `take` option to the query:
84+
85+
```typescript
86+
await prisma.user.findMany({
87+
take: 10,
88+
})
89+
```
90+
91+
2. Click the **Start new recording** button to begin a new recording and check for any performance improvements.
92+
3. In the project terminal, run the project with:
93+
```bash
94+
npm run dev
95+
```
96+
4. After the script completes, click the **Stop recording** button.
97+
5. Rename the recording to _Optimized queries_ by clicking the recording chip in the top left corner and typing "Optimized queries."
98+
99+
You can now compare performance improvements by navigating to the "Optimized queries" and "Unoptimized queries" recording tabs and observing the query latency differences.
100+
101+
---
102+
103+
## Next steps
104+
105+
- Check out the [Optimize docs](https://pris.ly/d/optimize).
106+
- Share your feedback on the [Prisma Discord](https://pris.ly/discord/).
107+
- Create issues and ask questions on [GitHub](https://github.com/prisma/prisma/).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
declare global {
2+
namespace NodeJS {
3+
interface ProcessEnv {
4+
DATABASE_URL: string
5+
OPTIMIZE_API_KEY: string | undefined
6+
}
7+
}
8+
}
9+
10+
export {}
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "script",
3+
"license": "MIT",
4+
"scripts": {
5+
"dev": "ts-node ./script.ts"
6+
},
7+
"dependencies": {
8+
"@faker-js/faker": "^8.4.1",
9+
"@prisma/client": "5.17.0",
10+
"@prisma/extension-optimize": "^1.0.0",
11+
"@types/node": "20.14.9"
12+
},
13+
"devDependencies": {
14+
"prisma": "5.17.0",
15+
"ts-node": "10.9.2",
16+
"typescript": "5.5.3"
17+
},
18+
"prisma": {
19+
"seed": "ts-node ./prisma/seed.ts"
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
generator client {
2+
provider = "prisma-client-js"
3+
previewFeatures = ["tracing"]
4+
}
5+
6+
datasource db {
7+
provider = "postgresql"
8+
url = env("DATABASE_URL")
9+
}
10+
11+
model User {
12+
id Int @id @default(autoincrement())
13+
email String @unique
14+
name String?
15+
posts Post[]
16+
}
17+
18+
model Post {
19+
id Int @id @default(autoincrement())
20+
title String
21+
content String?
22+
published Boolean @default(false)
23+
author User? @relation(fields: [authorId], references: [id])
24+
authorId Int?
25+
}
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { PrismaClient } from '@prisma/client'
2+
import { faker } from '@faker-js/faker'
3+
4+
const prisma = new PrismaClient()
5+
const TOTAL = 5000
6+
7+
const main = async () => {
8+
await prisma.post.deleteMany({})
9+
await prisma.user.deleteMany({})
10+
11+
for (let index = 0; index < TOTAL; index++) {
12+
await prisma.user.create({
13+
data: {
14+
email: `${Math.round(Math.random() * 1000)}${faker.internet.email()}`,
15+
name: faker.internet.displayName(),
16+
posts: {
17+
create: {
18+
title: faker.lorem.sentences(1),
19+
content: faker.lorem.text(),
20+
published: faker.datatype.boolean(),
21+
},
22+
},
23+
},
24+
})
25+
26+
console.log(`Inserted ${index + 1}/${TOTAL} item.`)
27+
}
28+
29+
console.log(`Inserted ${5000}/${TOTAL} item.`)
30+
}
31+
32+
main().then(() => console.log('🌿 Seeding completed.'))
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { prisma } from './utils'
2+
3+
// A `main` function so that we can use async/await
4+
async function main() {
5+
// A simple query to create the database connection as the database connection usually takes a lot of time
6+
await prisma.user.findFirst()
7+
8+
// Query 1
9+
await prisma.user.findMany()
10+
}
11+
12+
main()
13+
.then(async () => {
14+
await prisma.$disconnect()
15+
console.log('Done')
16+
})
17+
.catch(async (e) => {
18+
console.error(e)
19+
await prisma.$disconnect()
20+
process.exit(1)
21+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"sourceMap": true,
4+
"outDir": "dist",
5+
"strict": true,
6+
"lib": ["esnext"],
7+
"esModuleInterop": true
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { PrismaClient } from '@prisma/client'
2+
import { withOptimize } from '@prisma/extension-optimize'
3+
4+
export const prisma = new PrismaClient().$extends(
5+
withOptimize({
6+
token: process.env.OPTIMIZE_API_KEY!,
7+
}),
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './db'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DATABASE_URL=""
2+
OPTIMIZE_API_KEY=""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
*.env
4+
package-lock.json
5+
prisma/migrations

0 commit comments

Comments
 (0)