Skip to content

Commit

Permalink
Merge branch 'main' into feat/WEB-WEB-555-optimize-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
meletj authored Sep 10, 2024
2 parents 2ca7f57 + 797fe72 commit 31a05e3
Show file tree
Hide file tree
Showing 20 changed files with 630 additions and 7 deletions.
3 changes: 2 additions & 1 deletion cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@
"Nikolas",
"Supavisor",
"inshellisense",
"janedoe"
"janedoe",
"unindexed"
],
"patterns": [
{
Expand Down
23 changes: 22 additions & 1 deletion content/100-getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Bolt,
BorderBox,
BoxTitle,
Inspect,
Database,
Grid,
LinkCard,
Expand All @@ -33,11 +34,12 @@ Explore our products that make it easy to build and scale data-driven applicatio

[**<Database />Prisma ORM**](/orm/overview/introduction/what-is-prisma) is a next-generation Node.js and TypeScript ORM that unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion.

[**<Inspect />Prisma Optimize**](/optimize/) helps you analyze queries, generate insights, and provides recommendations to make your database queries faster.

[**<Bolt />Prisma Accelerate**](/accelerate) is a global database cache with scalable connection pooling to make your queries fast.

[**<SignalStream />Prisma Pulse**](/pulse) allows you to react to database changes with type-safe model streams in real-time.


</BorderBox>

</TopBlock>
Expand Down Expand Up @@ -195,3 +197,22 @@ Build real-time applications by subscribing to data changes in your database usi
link="https://github.com/prisma/prisma-examples?tab=readme-ov-file#prisma-pulse"
/>
</Grid>

## <Inspect color="#16A394" width="27" height="24" /> Prisma Optimize

Make your database queries faster by using the insights and recommendations generated by Prisma Optimize.

<Grid>
<LinkCard
icon="fa-solid fa-arrow-right"
title="Get started"
desc="Add Optimize to your app to gather useful insights and receive recommendations to improve query performance."
link="/optimize/getting-started"
/>
<LinkCard
icon="fa-brands fa-github"
title="Examples"
desc="Explore our ready-to-run examples using Prisma Optimize."
link="https://github.com/prisma/prisma-examples?tab=readme-ov-file#prisma-optimize"
/>
</Grid>
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ metaDescription: 'How Prisma optimizes queries under the hood'
tocDepth: 3
---

<TopBlock>

This guide describes ways to optimize query performance, debug performance issues, and how to tackle common performance issues such as the [n+1 problem](#solving-the-n1-problem).

</TopBlock>
:::tip

To debug slow queries, you can use [Prisma Optimize](/optimize) and follow the [recommendations](/optimize/recommendations) provided to improve query performance in your app.

:::

## Debugging performance issues

To help you debug and diagnose performance issues, you can [log query events at client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging), which allows you to see the generated queries, parameters, and durations.
To help you debug and diagnose performance issues, you can [log query events at client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging), which allows you to see the generated queries, parameters, and durations.

Alternatively, if you are only interested in the time taken to run a query, you can implement [logging middleware](/orm/prisma-client/client-extensions/middleware/logging-middleware).

Expand Down
27 changes: 27 additions & 0 deletions content/500-platform/10-about.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ In each workspace, you can:
- manage billing, i.e. select a [subscription plan](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs), configure payment methods, or view the invoice history.
- view the usage of your enabled PDP products across all projects in that workspace.
- invite other users to collaborate in the workspace.
- access the [Optimize dashboard](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-docs) to measure query performance and receive AI-powered recommendations.

#### Optimize

You can access Optimize within your [Prisma Data Platform account](https://console.prisma.io/optimize) workspace.

##### Accessing the Optimize dashboard

To access the Optimize dashboard in your desired workspace:

1. Click the **Optimize** tab on the left navigation.
2. Click the **Launch Optimize** button.

##### Generating an Optimize API key

To obtain the Optimize API key:

1. Navigate to the workspace where you want to use Optimize.
2. Ensure that Optimize is launched. If it isn't, click the **Launch Optimize** button.
3. If it isn't launched, spot the text in the Optimize dashboard that says, "Start by creating your first API key __here__ and start using Optimize," and click the __here__ link.
4. Click your profile name in the top right corner of the navbar.
5. Select **Settings**.
6. Click **Create API key**.
7. Enter a name for the API key in the **Name** field, then click **Create**.
8. Copy the API key and store it securely. This will be used in your project's [`.env` file](/optimize/getting-started#23-add-the-optimize-api-key-to-your-env-file) via the `"OPTIMIZE_API_KEY"`. Finally, click the **"I've stored it securely"** button.

You now have your Optimize API key.

### Project

Expand Down
92 changes: 92 additions & 0 deletions content/700-optimize/200-getting-started.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
title: 'Getting Started'
metaTitle: 'Getting started with Prisma Optimize'
metaDescription: 'Learn how to quickly set up and start using Prisma Optimize.'
tocDepth: 3
toc: true
---

## Prerequisites

Before you begin with Prisma Optimize, ensure you have the following:

- A [Prisma Data Platform account](https://console.prisma.io).
- A project using [Prisma Client](/orm/prisma-client) version `5.0.0` or higher (we recommend using the latest version).
- A PostgreSQL, MySQL/MariaDB, CockroachDB, or MS SQL Server database.

:::note

Prisma Optimize is intended for use in local environments. Learn more in the [FAQ](/optimize/faq#can-i-use-prisma-optimize-in-production).

:::

## 1. Launch Optimize

1. Log in to your [Prisma Data Platform account](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-page).
2. <a href="/platform/about#accessing-the-optimize-dashboard" target="_blank">Follow the instructions</a> to access and launch Prisma Optimize.

## 2. Add Optimize to your application

### 2.1. Update Your `schema.prisma` file

In the `generator` block of your Prisma schema, add the `tracing` preview feature:

```prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["tracing"]
}
```

Then, generate the Prisma Client:

```bash
npx prisma generate
```

### 2.2. Install the Optimize Prisma Client extension

Install the latest versions of Prisma Client and the Optimize extension:

```bash
npm install @prisma/client@latest @prisma/extension-optimize
```

### 2.3. Add the Optimize API Key to your `.env` file

<a href="/platform/about#generating-an-optimize-api-key" target="_blank">Generate a Prisma Optimize API key</a> and add it to your `.env` file:

```bash
OPTIMIZE_API_KEY="YOUR_OPTIMIZE_API_KEY"
```

### 2.4. Extend your Prisma Client instance

Extend your existing Prisma Client instance with the Optimize extension:

```ts
import { PrismaClient } from "@prisma/client";
import { withOptimize } from "@prisma/extension-optimize";

const prisma = new PrismaClient().$extends(
withOptimize({ token: process.env.OPTIMIZE_API_KEY }),
);
```

### 2.5. Use Prisma Optimize to generate insights

Follow these steps to start generating query insights with Prisma Optimize:

1. In the Optimize dashboard, click the **Start recording** button, then run your app and execute some Prisma queries while recording is active.
2. After your app runs and generates insights based on the executed Prisma queries, click the **Stop recording** button.
3. Explore [individual query details](/optimize/recordings#data-captured-in-a-recording-session) by clicking on them, and check the **Recommendations** tab for any suggested improvements to enhance query performance.

:::info
Use [Prisma AI](/optimize/prisma-ai) to understand recommendations and apply them within your Prisma model context.
:::

For a hands-on learning experience, try out the [step-by-step example](https://github.com/prisma/prisma-examples/tree/latest/optimize/starter).

## Need help?

If you need assistance, reach out in the `#help-and-questions` channel on our [Discord](https://pris.ly/discord), or connect with our community to see how others are using Optimize.
47 changes: 47 additions & 0 deletions content/700-optimize/300-recordings.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: 'Recordings'
metaTitle: 'Optimize: Recordings'
metaDescription: "Learn about using Optimize's recording feature."
tocDepth: 3
toc: true
---

The recordings feature helps developers debug and isolate sets of queries into distinct sessions, known as recordings. This targeted approach enables precise performance analysis and optimization by preventing the mixing of queries from different applications or test rounds, leading to clearer insights and more effective debugging.

## Managing a recording session

You can manually start and stop recording sessions via the [Optimize dashboard](https://console.prisma.io/optimize) by clicking the **Start Recording** and **Stop Recording** buttons.

:::warning
A recording will automatically stop if the 10k query limit is reached or if the Prisma schema of the app is changed.
:::

## Identifying a recording session

You can rename and tag your recording sessions for easy identification and context. Click on the default name of the session and type the desired name.

## Data captured in a recording session

Each recording session captures detailed insights about the queries executed in your app, including:

- All queries executed during the session.
- The raw query generated and sent to the database by Prisma ORM as **Raw Query**.
- The number of times a query pattern was executed, listed as **Count**.
- [Query performance metrics](/optimize/performance-metrics).
- Errors encountered during query execution.

Each recording can include up to 10k queries. There are no limits on storage retention.

## Recommendations from a recording session

When a recording session ends, Optimize generates recommendations such as:

- [Excessive number of rows returned](/optimize/recommendations/excessive-number-of-rows-returned)
- [Full table scans caused by LIKE operations](/optimize/recommendations/full-table-scans-caused-by-like-operations)
- [Queries on unindexed columns](/optimize/recommendations/queries-on-unindexed-columns)

:::info
Use [Prisma AI](/optimize/prisma-ai) to ask follow-up questions about a recommendation.
:::

Learn more about the recommendations generated by Optimize [here](/optimize/recommendations).
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: 'Excessive number of rows returned'
metaTitle: 'Optimize Recommendations: Excessive number of rows returned'
metaDescription: "Learn about the recommendation provided by Optimize for excessive number of rows returned."
tocDepth: 3
toc: true
---

Optimize provides recommendations to help you identify and resolve performance issues caused by excessive number of rows returned from a query.

The following query targeting a `User` model does not provide a [`take` option](/orm/reference/prisma-client-reference#findmany):

```ts
await prisma.user.findMany({ where: { email: "[email protected]" }})
```

## What is the problem?

When a query is executed without specifying a limit, it will return all relevant rows, which can lead to several issues:

### User experience

- **Viewing data:** Users typically need only a portion of the data at any given time, not all of it at once.
- **Impact on the user's device:** Displaying all the data at once can strain the user's device resources. For example, loading thousands of rows in a web application can slow down or freeze the browser, consuming significant memory and CPU resources.
- **Waiting time:** Retrieving a large number of rows can significantly increase the time it takes to get the data from the database to the user's device.

### Resource Utilization

- **Unnecessary data load:** Processing more data than required wastes valuable resources.
- **Memory usage:** Excessive memory consumption can lead to inefficiency and, in severe cases, cause the system to run out of memory, disrupting the service.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: 'Queries on unindexed columns'
metaTitle: 'Optimize Recommendations: Queries on unindexed columns'
metaDescription: "Learn about the recommendation provided by Optimize for queries on unindexed columns."
tocDepth: 3
toc: true
---

Optimize provides recommendations to help you identify and resolve performance issues caused by missing database indexes.

The following queries targeting the `User` model use a [`where` property](/orm/prisma-client/queries/filtering-and-sorting) to filter on columns that do not have indexes:

```ts
await prisma.user.findFirst({
where: {
name: "Marc"
}
})

await prisma.user.findFirst({
where: {
name: "Jon"
}
})

await prisma.user.count({
where: {
name: "Nikolas"
}
})
```

## What is the problem?

An index allows the database to retrieve data more quickly, similar to how an index in a book helps you locate information without reading every page.

When using Prisma with a `where` property, if no indexes are defined for the relevant columns, the database may need to scan every row in the table (a *“full table scan”*) to find matches. This can be undesirable for several reasons:

### User experience

For large datasets, if the database must scan the entire table to find matching rows, users will experience longer waiting times.

### Resource utilization

- **High CPU usage:** Scanning large tables can significantly increase CPU usage, degrading overall system performance.
- **Memory consumption:** More memory is required to process and store data during a full table scan.
- **Disk I/O:** Full table scans increase disk input/output operations, potentially slowing down other database activities.

:::warning

While these issues might not appear in development due to smaller datasets, they can become *significant* problems in production, where datasets are typically much larger.

:::


## More on database indexes

### How indexes work

Indexes create a data structure that stores the indexed column's values along with pointers to the corresponding rows in the table. When you query the database using an indexed column, the database can use this index to quickly locate the relevant rows instead of scanning the entire table.

### The trade-offs of indexing

- **Space vs. time:** Indexing requires additional storage space to save index data, but it significantly speeds up data retrieval.
- **Update overhead:** Every time data is added to, updated in, or removed from your table, there is an overhead to keep the indexes up to date, which can slow down write operations.

### When to use indexes

- **Large datasets:** Indexes are particularly beneficial for tables with a large number of rows.
- **Frequent queries with filtering or sorting:** Use indexes on columns that are frequently used for [filtering or sorting](/orm/prisma-client/queries/filtering-and-sorting#filtering).
- **Looking up related data:** Use indexes on foreign key columns to speed up the retrieval of related records, such as when using [`include`](/orm/prisma-client/queries/relation-queries#include-a-relation).

### When not to use indexes

- **Small tables:** For tables with very few rows, the overhead of maintaining indexes might not be worth the performance gain.
- **Write-heavy tables:** Indexes can slow down write operations (`create`, `update`, `delete`) because the index needs to be updated as well. Avoid excessive indexing on models with frequent write operations.
- **Infrequently accessed tables:** If a table is rarely accessed, the benefits of indexing may not justify the overhead.
- **Columns with large data:** Indexing columns with large data can lead to higher storage requirements and might not provide significant performance improvements.
- **Rarely filtered columns:** If a table is often accessed but rarely filtered by a specific column, creating an index on that column may not be beneficial.

:::warning

Even if you index a column, the database may not always use it. Many database management systems, such as PostgreSQL and MySQL, have a *query optimizer* that evaluates multiple execution plans and selects the one it estimates to be most efficient. In some cases, this may involve ignoring an existing index in favor of a different execution plan that it determines will perform better for that specific query.

:::
Loading

0 comments on commit 31a05e3

Please sign in to comment.