Skip to content

Commit

Permalink
feat: add repeated query (#6815)
Browse files Browse the repository at this point in the history
* feat: add repeated query

* feat: add example 4

* fix: change the title

* test: check url

* feat: cleanup

* Update optimize/optimize-select-returning-all/README.md

* cleanup: perform cleanup

* enhance: add more context

* fix: make the line more clear
  • Loading branch information
ankur-arch authored Oct 18, 2024
1 parent 28c3ab7 commit d5806f0
Show file tree
Hide file tree
Showing 30 changed files with 699 additions and 3 deletions.
6 changes: 6 additions & 0 deletions optimize/optimize-excessive-rows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ Perform a database migration to prepare the project:
npx prisma migrate dev --name init
```

If the database isn't seeded, run the following command to seed it:

```bash
npx prisma db seed
```

### 4. Open the Optimize dashboard

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:
Expand Down
2 changes: 1 addition & 1 deletion optimize/optimize-excessive-rows/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PrismaClient } from '@prisma/client'
import { faker } from '@faker-js/faker'

const prisma = new PrismaClient()
const TOTAL = 5000
const TOTAL = 30

const main = async () => {
await prisma.post.deleteMany({})
Expand Down
6 changes: 6 additions & 0 deletions optimize/optimize-full-table-scan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ Perform a database migration to prepare the project:
npx prisma migrate dev --name init
```

If the database isn't seeded, run the following command to seed it:

```bash
npx prisma db seed
```

### 4. Open the Optimize dashboard

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:
Expand Down
2 changes: 1 addition & 1 deletion optimize/optimize-full-table-scan/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PrismaClient } from '@prisma/client'
import { faker } from '@faker-js/faker'

const prisma = new PrismaClient()
const TOTAL = 5000
const TOTAL = 20

const main = async () => {
await prisma.post.deleteMany({})
Expand Down
2 changes: 2 additions & 0 deletions optimize/optimize-repeated-query/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DATABASE_URL=""
OPTIMIZE_API_KEY=""
5 changes: 5 additions & 0 deletions optimize/optimize-repeated-query/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
*.env
package-lock.json
prisma/migrations
188 changes: 188 additions & 0 deletions optimize/optimize-repeated-query/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Prisma Optimize Example: Applying the "Repeated query" Recommendation

This repository demonstrates how to use [Prisma Optimize](https://pris.ly/optimize) to improve query performance using the "Repeated query" recommendation.

## Prerequisites

To successfully run the project, you will need the following:

1. A **database connection string** supported by Prisma Optimize and Prisma Accelerate.
2. An Optimize API key, which you can obtain from your [Prisma Data Platform](https://pris.ly/pdp) account.
3. An Accelerate API key, which you can obtain from your [Prisma Data Platform](https://pris.ly/pdp) account.

## Getting started

### 1. Clone the repository

Clone the repository, navigate into it, and install the dependencies:

```bash
git clone [email protected]:prisma/prisma-examples.git --depth=1
cd prisma-examples/optimize/optimize-repeated-query
npm install
```

### 2. Configure environment variables

Create a `.env` file in the root of the project directory:

```bash
cp .env.example .env
```

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:

```env
# .env
DATABASE_URL="__YOUR_DATABASE_CONNECTION_STRING__"
# Replace __YOUR_DATABASE_CONNECTION_STRING__ with your actual connection string.
OPTIMIZE_API_KEY="your_secure_optimize_api_key"
```

- `DATABASE_URL`: The connection string to your database.
- `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.

### 3. Set up the project

Perform a database migration to prepare the project:

```bash
npx prisma migrate dev --name init
```

If the database isn't seeded, run the following command to seed it:

```bash
npx prisma db seed
```

### 4. Open the Optimize dashboard

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:

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.
2. If Optimize hasn't been launched yet, click the **Launch Optimize** button.
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.

### 5. Run the script

Let's run the [script with unoptimized Prisma queries](./script.ts):

1. In the Optimize dashboard, click the **Start new recording** button.
2. In the project terminal, run the project with:

```bash
npm run dev
```

3. After the script completes, you'll see a log saying "Done." Then, in the Optimize dashboard, click the **Stop recording** button.
4. Observe the queries with high latencies highlighted in red, and review the recommendations in the **Recommendations** tab. You should see the recommendation **Repeated query** and click on it.
> For more insights on this recommendation, click the **Ask AI** button and interact with the [AI Explainer](https://pris.ly/optimize-ai-chatbot) chatbot.
5. To create a reference for comparison with other recordings, rename the recording labelled "Recording 1" to _Unoptimized queries_ by clicking the green recording label chip in the top left corner and typing "Unoptimized queries".
![Rename recording](./images/edit-recording-name-chip.png)
### Add Prisma Accelerate to the project
To apply the recommendation, you need to add Prisma Accelerate to the project. To do that:
1. Use your database connection string and enable Prisma Accelerate in your [Prisma Data Platform account](https://pris.ly/pdp).
2. Install the required dependencies:
```bash
npm install @prisma/client@latest @prisma/extension-accelerate
```
3. Update [the database connection string to use the Accelerate connection string](https://www.prisma.io/docs/accelerate/getting-started#21-update-your-database-connection-string).
4. Regenerate `PrismaClient`:
```bash
npx prisma generate --no-engine
```
5. Extend `PrismaClient` by using the Accelerate client extension in [utils/db.ts](./utils/db.ts) folder:
```diff
import { PrismaClient } from '@prisma/client'
+ import { withAccelerate } from '@prisma/extension-accelerate'
import { withOptimize } from '@prisma/extension-optimize'
export const prisma = new PrismaClient().$extends(
withOptimize({
apiKey: process.env.OPTIMIZE_API_KEY!,
}),
)
+ .$extends(withAccelerate());
```
Afterward, continue with the next steps to complete the recommendation.
### Optimize example: Applying the "Repeated query" recommendation
Next, let’s follow the recommendation provided by Optimize to improve the performance of the queries:
1. To enhance the performance of [**Query 1**](./script.ts) through [**Query 5**](./script.ts) by addressing the "Repeated query" recommendation, add a [cache strategy](https://prisma.io/docs/accelerate/caching) to the queries:
```diff
// Query 1
await prisma.user.findFirst({
select: {
name: true,
},
+ cacheStrategy: {
+ ttl: 120
+ }
})
// Query 2
await prisma.user.findFirst({
select: {
name: true,
},
+ cacheStrategy: {
+ ttl: 120
+ }
})
// Query 3
await prisma.user.findFirst({
select: {
name: true,
},
+ cacheStrategy: {
+ ttl: 120
+ }
})
// Query 4
await prisma.user.findFirst({
select: {
name: true,
},
+ cacheStrategy: {
+ ttl: 120
+ }
})
// Query 5
await prisma.user.findFirst({
select: {
name: true,
},
+ cacheStrategy: {
+ ttl: 120
+ }
})
```
2. Click the **Start new recording** button to begin a new recording and check for any performance improvements.
3. In the project terminal, run the project with:
```bash
npm run dev
```
4. After the script completes, click the **Stop recording** button.
5. Rename the recording labelled "Recording 1" to _Optimized queries_ by clicking the recording chip in the top left corner and typing "Optimized queries."
You can now compare performance improvements by navigating to the "Optimized queries" and "Unoptimized queries" recording tabs and observing the query latency differences.
---
## Next steps
- Check out the [Optimize docs](https://pris.ly/d/optimize).
- Share your feedback on the [Prisma Discord](https://pris.ly/discord/).
- Create issues and ask questions on [GitHub](https://github.com/prisma/prisma/).
10 changes: 10 additions & 0 deletions optimize/optimize-repeated-query/environment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string
OPTIMIZE_API_KEY: string | undefined
}
}
}

export {}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions optimize/optimize-repeated-query/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "script",
"license": "MIT",
"scripts": {
"dev": "ts-node ./script.ts"
},
"dependencies": {
"@faker-js/faker": "9.0.3",
"@prisma/client": "5.20.0",
"@prisma/extension-optimize": "1.0.1",
"@types/node": "20.16.11"
},
"devDependencies": {
"prisma": "5.20.0",
"ts-node": "10.9.2",
"typescript": "5.6.3"
},
"prisma": {
"seed": "ts-node ./prisma/seed.ts"
}
}
26 changes: 26 additions & 0 deletions optimize/optimize-repeated-query/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["tracing"]
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}

45 changes: 45 additions & 0 deletions optimize/optimize-repeated-query/prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { PrismaClient } from '@prisma/client'
import { faker } from '@faker-js/faker'

const prisma = new PrismaClient()
const TOTAL = 20

const main = async () => {
await prisma.post.deleteMany({})
await prisma.user.deleteMany({})

for (let index = 0; index < TOTAL - 1; index++) {
await prisma.user.create({
data: {
email: `${Math.round(Math.random() * 1000)}${faker.internet.email()}`,
name: faker.internet.displayName(),
posts: {
create: {
title: faker.lorem.sentences(1),
content: faker.lorem.text(),
published: faker.datatype.boolean(),
},
},
},
})

console.log(`Inserted ${index + 1}/${TOTAL} item.`)
}

await prisma.user.create({
data: {
name: 'Nikolas Burk',
email: '[email protected]',
posts: {
create: {
title: 'The great gatsby',
content: 'The story had a nice ending.',
},
},
},
})

console.log(`Inserted ${5000}/${TOTAL} item.`)
}

main().then(() => console.log('🌿 Seeding completed.'))
Loading

0 comments on commit d5806f0

Please sign in to comment.