diff --git a/_includes/v21.2/performance/statement-contention.md b/_includes/v21.2/performance/statement-contention.md index e0249eec440..63f9832d4f2 100644 --- a/_includes/v21.2/performance/statement-contention.md +++ b/_includes/v21.2/performance/statement-contention.md @@ -13,4 +13,4 @@ Find the transactions and statements within the transactions that are experienci > SELECT * FROM movr.crdb_internal.cluster_contended_tables; ~~~ -After identifying the transactions or statements that are experiencing contention, follow the steps in [Understanding and avoiding transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +After you identify the transactions or statements that are causing contention, follow the steps in the next section [to avoid contention](performance-best-practices-overview.html#avoid-transaction-contention). diff --git a/v21.2/advanced-client-side-transaction-retries.md b/v21.2/advanced-client-side-transaction-retries.md index a2b3cdfbca9..fbc2828f497 100644 --- a/v21.2/advanced-client-side-transaction-retries.md +++ b/v21.2/advanced-client-side-transaction-retries.md @@ -12,7 +12,7 @@ If you are an application developer who needs to implement an application-level ## Overview -To improve the performance of transactions that fail due to [contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention), CockroachDB includes a set of statements (listed below) that let you retry those transactions. Retrying transactions using these statements has the following benefits: +To improve the performance of transactions that fail due to [contention](performance-best-practices-overview.html#transaction-contention), CockroachDB includes a set of statements (listed below) that let you retry those transactions. Retrying transactions using these statements has the following benefits: 1. When you use savepoints, you "hold your place in line" between attempts. Without savepoints, you're starting from scratch every time. 2. Transactions increase their priority each time they're retried, increasing the likelihood they will succeed. This has a lesser effect than #1. diff --git a/v21.2/architecture/admission-control.md b/v21.2/architecture/admission-control.md index 28e68537622..2667a5b9af8 100644 --- a/v21.2/architecture/admission-control.md +++ b/v21.2/architecture/admission-control.md @@ -39,7 +39,7 @@ Admission control should be used when overall cluster health is good but some no When admission control is enabled, request and response operations get sorted into work queues where the operations are organized by priority and transaction start time. -Higher priority operations are processed first. The criteria for determining higher and lower priority operations is different at each processing layer, and is determined by the CPU and storage I/O of the operation. Write operations in the [KV storage layer](storage-layer.html) in particular are often the cause of performance bottlenecks, and enabling admission control prevents [the Pebble storage engine](../cockroach-start.html#storage-engine) from experiencing high read amplification. Critical cluster operations like node heartbeats are processed as high priority, as are transactions that hold locks in order to avoid [contention](../performance-recipes.html#contention) by releasing locks. +Higher priority operations are processed first. The criteria for determining higher and lower priority operations is different at each processing layer, and is determined by the CPU and storage I/O of the operation. Write operations in the [KV storage layer](storage-layer.html) in particular are often the cause of performance bottlenecks, and enabling admission control prevents [the Pebble storage engine](../cockroach-start.html#storage-engine) from experiencing high read amplification. Critical cluster operations like node heartbeats are processed as high priority, as are transactions that hold locks in order to avoid [contention](../performance-recipes.html#transaction-contention) by releasing locks. The transaction start time is used within the priority queue and gives preference to operations with earlier transaction start times. For example, within the high priority queue operations with an earlier transaction start time are processed first. diff --git a/v21.2/architecture/transaction-layer.md b/v21.2/architecture/transaction-layer.md index eac97e5a98d..307ae1af11d 100644 --- a/v21.2/architecture/transaction-layer.md +++ b/v21.2/architecture/transaction-layer.md @@ -332,7 +332,7 @@ The transaction coordinator is able to do this while maintaining correctness gua For an example showing how the Parallel Commits feature works in more detail, see [Parallel Commits - step by step](#parallel-commits-step-by-step). {{site.data.alerts.callout_info}} -The latency until intents are resolved is unchanged by the introduction of Parallel Commits: two rounds of consensus are still required to resolve intents. This means that [contended workloads](../performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) are expected to profit less from this feature. +The latency until intents are resolved is unchanged by the introduction of Parallel Commits: two rounds of consensus are still required to resolve intents. This means that [contended workloads](../performance-best-practices-overview.html#transaction-contention) are expected to profit less from this feature. {{site.data.alerts.end}} #### Parallel Commits - step by step @@ -396,7 +396,7 @@ Additionally, when other transactions encounter a transaction in `STAGING` state The non-blocking transaction protocol and replication scheme differ from standard read-write transactions as follows: - Non-blocking transactions use a replication scheme over the [ranges](overview.html#terms) they operate on that allows all followers in these ranges to serve consistent (non-stale) reads. -- Non-blocking transactions are minimally disruptive to reads over the data they modify, even in the presence of read/write [contention](../performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +- Non-blocking transactions are minimally disruptive to reads over the data they modify, even in the presence of read/write [contention](../performance-best-practices-overview.html#transaction-contention). These properties of non-blocking transactions combine to provide predictable read latency for a configurable subset of data in [global deployments](../multiregion-overview.html). This is useful since there exists a sizable class of data which is heavily skewed towards read traffic. diff --git a/v21.2/build-a-spring-app-with-cockroachdb-jdbc.md b/v21.2/build-a-spring-app-with-cockroachdb-jdbc.md index efef3f6cc60..7d998d1ca92 100644 --- a/v21.2/build-a-spring-app-with-cockroachdb-jdbc.md +++ b/v21.2/build-a-spring-app-with-cockroachdb-jdbc.md @@ -784,7 +784,7 @@ On verifying that the transaction is active (using `TransactionSynchronizationMa #### Transaction retries -Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. +Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. In this application, transaction retry logic is written into the methods of the `RetryableTransactionAspect` class. This class is declared an aspect with the `@Aspect` annotation. The `@Order` annotation on this aspect class is passed `Ordered.LOWEST_PRECEDENCE-2`, a level of precedence above the primary transaction advisor. This indicates that the transaction retry advisor must run outside the context of a transaction. Here are the contents of [`RetryableTransactionAspect.java`](https://github.com/cockroachlabs/roach-data/blob/master/roach-data-jdbc/src/main/java/io/roach/data/jdbc/RetryableTransactionAspect.java): diff --git a/v21.2/build-a-spring-app-with-cockroachdb-jpa.md b/v21.2/build-a-spring-app-with-cockroachdb-jpa.md index 9e16114e6d8..24e342cd679 100644 --- a/v21.2/build-a-spring-app-with-cockroachdb-jpa.md +++ b/v21.2/build-a-spring-app-with-cockroachdb-jpa.md @@ -673,7 +673,7 @@ For more details about advice ordering, see [Advice Ordering](https://docs.sprin #### Transaction retries -Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. +Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. In this application, transaction retry logic is written into the methods of the `RetryableTransactionAspect` class, declared an aspect with the `@Aspect` annotation. Here are the contents of [`RetryableTransactionAspect.java`](https://github.com/cockroachlabs/roach-data/blob/master/roach-data-jpa/src/main/java/io/roach/data/jpa/RetryableTransactionAspect.java): diff --git a/v21.2/build-a-spring-app-with-cockroachdb-mybatis.md b/v21.2/build-a-spring-app-with-cockroachdb-mybatis.md index 2fc973c606c..772fbd14bc2 100644 --- a/v21.2/build-a-spring-app-with-cockroachdb-mybatis.md +++ b/v21.2/build-a-spring-app-with-cockroachdb-mybatis.md @@ -371,7 +371,7 @@ Instances of the `BatchResults` class, defined in `src/main/java/com/example/coc MyBatis-Spring supports Spring's [declarative, aspect-oriented transaction management syntax](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative), including the [`@Transactional`](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-annotations) annotation and [AspectJ's AOP annotations](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-aspectj). -Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. In this application, transaction retry logic is written into the methods of the `RetryableTransactionAspect` class, defined in `src/main/java/com/example/cockroachdemo/RetryableTransactionAspect.java`: +Transactions may require retries if they experience deadlock or [transaction contention](performance-best-practices-overview.html#transaction-contention) that cannot be resolved without allowing [serialization](demo-serializable.html) anomalies. To handle transactions that are aborted due to transient serialization errors, we highly recommend writing [client-side transaction retry logic](transactions.html#client-side-intervention) into applications written on CockroachDB. In this application, transaction retry logic is written into the methods of the `RetryableTransactionAspect` class, defined in `src/main/java/com/example/cockroachdemo/RetryableTransactionAspect.java`: {% include_cached copy-clipboard.html %} ~~~ java diff --git a/v21.2/crdb-internal.md b/v21.2/crdb-internal.md index ac36cc1c28f..81797585fa3 100644 --- a/v21.2/crdb-internal.md +++ b/v21.2/crdb-internal.md @@ -24,10 +24,10 @@ Table | Description `active_range_feeds` | Contains information about [range feeds](architecture/distribution-layer.html) on nodes in your cluster. `backward_dependencies` | Contains information about backward dependencies. `builtin_functions` | Contains information about supported [functions](functions-and-operators.html). -`cluster_contended_indexes` | Contains information about [contended](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) indexes in your cluster. -`cluster_contended_keys` | Contains information about [contended](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) keys in your cluster. -`cluster_contended_tables` | Contains information about [contended](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) tables in your cluster. -`cluster_contention_events` | Contains information about [contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) in your cluster. +`cluster_contended_indexes` | Contains information about [contended](performance-best-practices-overview.html#transaction-contention) indexes in your cluster. +`cluster_contended_keys` | Contains information about [contended](performance-best-practices-overview.html#transaction-contention) keys in your cluster. +`cluster_contended_tables` | Contains information about [contended](performance-best-practices-overview.html#transaction-contention) tables in your cluster. +`cluster_contention_events` | Contains information about [contention](performance-best-practices-overview.html#transaction-contention) in your cluster. `cluster_database_privileges` | Contains information about the [database privileges](authorization.html#privileges) on your cluster. `cluster_distsql_flows` | Contains information about the flows of the [DistSQL execution](architecture/sql-layer.html#distsql) scheduled in your cluster. `cluster_inflight_traces` | Contains information about in-flight [tracing](show-trace.html) in your cluster. diff --git a/v21.2/delete-data.md b/v21.2/delete-data.md index e468e06860c..4c380ee182d 100644 --- a/v21.2/delete-data.md +++ b/v21.2/delete-data.md @@ -238,7 +238,7 @@ Reference information related to this task: - [Disk space usage after deletes](delete.html#disk-space-usage-after-deletes) - [`TRUNCATE`](truncate.html) - [`DROP TABLE`](drop-table.html) -- [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) +- [Transaction Contention](performance-best-practices-overview.html#transaction-contention) Other common tasks: diff --git a/v21.2/developer-guide-overview.md b/v21.2/developer-guide-overview.md index fb35cc865c9..428ba745be1 100644 --- a/v21.2/developer-guide-overview.md +++ b/v21.2/developer-guide-overview.md @@ -37,7 +37,7 @@ Managing transactions is an important part of CockroachDB application developmen CockroachDB guarantees [`SERIALIZABLE`](https://en.wikipedia.org/wiki/Serializability) transaction [isolation](https://en.wikipedia.org/wiki/Isolation_(database_systems)) (the "I" of ACID semantics). If transactions are executed concurrently, the final state of the database will appear as if the transactions were executed serially. `SERIALIZABLE` isolation, the strictest level of isolation, provides the highest level of data consistency and protects against concurrency-based attacks and bugs. -To guarantee `SERIALIZABLE` isolation, CockroachDB locks the data targeted by an open transaction. If a separate transaction attempts to modify data that are locked by an open transaction, the newest transaction will not succeed, as committing it could result in a violation of the `SERIALIZABLE` isolation level. This scenario is called *transaction contention*, and should be avoided when possible. For a more detailed explanation of transaction contention, and tips on how to avoid it, see [Understand and Avoid Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +To guarantee `SERIALIZABLE` isolation, CockroachDB locks the data targeted by an open transaction. If a separate transaction attempts to modify data that are locked by an open transaction, the newest transaction will not succeed, as committing it could result in a violation of the `SERIALIZABLE` isolation level. This scenario is called *transaction contention*, and should be avoided when possible. For a more detailed explanation of transaction contention, and tips on how to avoid it, see [Understand and Avoid Transaction Contention](performance-best-practices-overview.html#transaction-contention). #### Transaction retries diff --git a/v21.2/error-handling-and-troubleshooting.md b/v21.2/error-handling-and-troubleshooting.md index e22c1eb276b..f5c7d06c94a 100644 --- a/v21.2/error-handling-and-troubleshooting.md +++ b/v21.2/error-handling-and-troubleshooting.md @@ -24,7 +24,7 @@ If you aren't sure whether SQL query performance needs to be improved on your cl ## Transaction retry errors -Messages with the Postgres error code `40001` indicate that a transaction failed because it [conflicted with another concurrent or recent transaction accessing the same data](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). The transaction needs to be retried by the client. +Messages with the Postgres error code `40001` indicate that a transaction failed because it [conflicted with another concurrent or recent transaction accessing the same data](performance-best-practices-overview.html#transaction-contention). The transaction needs to be retried by the client. If your language's client driver or ORM implements transaction retry logic internally (e.g., if you are using Python and [SQLAlchemy with the CockroachDB dialect](build-a-python-app-with-cockroachdb-sqlalchemy.html)), then you do not need to handle this logic from your application. @@ -33,7 +33,7 @@ If your driver or ORM does not implement this logic, then you will need to imple {% include {{page.version.version}}/misc/client-side-intervention-example.md %} {{site.data.alerts.callout_info}} -If a consistently high percentage of your transactions are resulting in transaction retry errors, then you may need to evaluate your schema design and data access patterns to find and remove sources of contention. For more information about contention, see [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +If a consistently high percentage of your transactions are resulting in transaction retry errors, then you may need to evaluate your schema design and data access patterns to find and remove sources of contention. For more information about contention, see [Transaction Contention](performance-best-practices-overview.html#transaction-contention). For more information about what is causing a specific transaction retry error code, see the [Transaction Retry Error Reference](transaction-retry-error-reference.html). {{site.data.alerts.end}} @@ -77,7 +77,7 @@ Reference information related to this page: - [Common errors](common-errors.html) - [Transactions](transactions.html) - [Transaction retries](transactions.html#client-side-intervention) -- [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) +- [Transaction Contention](performance-best-practices-overview.html#transaction-contention) - [SQL Layer][sql] Other common tasks: diff --git a/v21.2/flyway.md b/v21.2/flyway.md index fd02be2bfdf..9d8aabba431 100644 --- a/v21.2/flyway.md +++ b/v21.2/flyway.md @@ -163,7 +163,7 @@ When used with most databases, [Flyway wraps the statements in a migration withi ### Transaction retries -When multiple, concurrent transactions or statements are issued to a single CockroachDB cluster, [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) can cause schema migrations to fail. In the event of transaction contention, CockroachDB returns a `40001 SQLSTATE` (i.e., a serialization failure), and Flyway automatically retries the migration. For more information about client-side transaction retries in CockroachDB, see [Transaction Retries](transactions.html#transaction-retries). +When multiple, concurrent transactions or statements are issued to a single CockroachDB cluster, [transaction contention](performance-best-practices-overview.html#transaction-contention) can cause schema migrations to fail. In the event of transaction contention, CockroachDB returns a `40001 SQLSTATE` (i.e., a serialization failure), and Flyway automatically retries the migration. For more information about client-side transaction retries in CockroachDB, see [Transaction Retries](transactions.html#transaction-retries). ### Transactional schema changes diff --git a/v21.2/insert-data.md b/v21.2/insert-data.md index f472d22fa6e..05ae0db0719 100644 --- a/v21.2/insert-data.md +++ b/v21.2/insert-data.md @@ -114,7 +114,7 @@ Reference information related to this task: - [Import performance](import.html#performance) - [`INSERT`](insert.html) - [`UPSERT`](upsert.html) -- [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) +- [Transaction Contention](performance-best-practices-overview.html#transaction-contention) - [Multi-row DML best practices](performance-best-practices-overview.html#dml-best-practices) - [Insert Multiple Rows](insert.html#insert-multiple-rows-into-an-existing-table) diff --git a/v21.2/liquibase.md b/v21.2/liquibase.md index dd14f6a06d2..391025bdb50 100644 --- a/v21.2/liquibase.md +++ b/v21.2/liquibase.md @@ -487,7 +487,7 @@ If `runInTransaction="false"` for a changeset, and an error occurs while Liquid ### Transaction retries -When multiple, concurrent transactions or statements are issued to a single CockroachDB cluster, [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) can cause schema migrations to fail. In the event of transaction contention, CockroachDB returns a `40001 SQLSTATE` (i.e., a serialization failure). +When multiple, concurrent transactions or statements are issued to a single CockroachDB cluster, [transaction contention](performance-best-practices-overview.html#transaction-contention) can cause schema migrations to fail. In the event of transaction contention, CockroachDB returns a `40001 SQLSTATE` (i.e., a serialization failure). Liquibase does not automatically retry transactions. To handle transaction failures, we recommend writing client-side transaction retry logic. For more information about client-side transaction retries in CockroachDB, see [Transaction Retries](transactions.html#transaction-retries). diff --git a/v21.2/make-queries-fast.md b/v21.2/make-queries-fast.md index ec178e2c49c..d913b02c6ea 100644 --- a/v21.2/make-queries-fast.md +++ b/v21.2/make-queries-fast.md @@ -474,7 +474,7 @@ You can avoid contention with the following strategies: - Make transactions smaller by operating on less data per transaction. This will offer fewer opportunities for transactions' data access to overlap. - [Split the table across multiple ranges](split-at.html) to distribute its data across multiple nodes for better load balancing of some write-heavy workloads. -For more information about how to avoid performance problems caused by contention, see [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +For more information about how to avoid performance problems caused by contention, see [Transaction Contention](performance-best-practices-overview.html#transaction-contention). ## Cluster topology @@ -491,7 +491,7 @@ Reference information: - [SQL Tuning with `EXPLAIN`](sql-tuning-with-explain.html) - [Joins](joins.html) - [CockroachDB Performance](performance.html) -- [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention) +- [Transaction Contention](performance-best-practices-overview.html#transaction-contention) - [Topology Patterns](topology-patterns.html) Specific tasks: diff --git a/v21.2/migrate-from-oracle.md b/v21.2/migrate-from-oracle.md index df586925f64..a0dd02a6f84 100644 --- a/v21.2/migrate-from-oracle.md +++ b/v21.2/migrate-from-oracle.md @@ -325,7 +325,7 @@ Both Oracle and CockroachDB support [multi-statement transactions](transactions. Regarding locks, Cockroach utilizes a [lightweight latch](architecture/transaction-layer.html#latch-manager) to serialize access to common keys across concurrent transactions. Oracle and CockroachDB transaction control flows only have a few minor differences; for more details, refer to [Transactions - SQL statements](transactions.html#sql-statements). -As CockroachDB does not allow serializable anomalies, [transactions](begin-transaction.html) may experience deadlocks or [read/write contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). This is expected during concurrency on the same keys. These can be addressed with either [automatic retries](transactions.html#automatic-retries) or [client-side intervention techniques](transactions.html#client-side-intervention). +As CockroachDB does not allow serializable anomalies, [transactions](begin-transaction.html) may experience deadlocks or [read/write contention](performance-best-practices-overview.html#transaction-contention). This is expected during concurrency on the same keys. These can be addressed with either [automatic retries](transactions.html#automatic-retries) or [client-side intervention techniques](transactions.html#client-side-intervention). ### SQL dialect diff --git a/v21.2/movr-flask-use-case.md b/v21.2/movr-flask-use-case.md index 4a691c73a27..bc60be8b0c6 100644 --- a/v21.2/movr-flask-use-case.md +++ b/v21.2/movr-flask-use-case.md @@ -25,7 +25,7 @@ In the [example deployment](movr-flask-deployment.html), the application and the If the MovR application and database are deployed in a single region, latency can become a serious problem when users are located in cities outside the deployment region. Deploying the application and database in multiple regions is not guaranteed to improve latency if client requests are sent to any regional deployment, without consideration for the client's location. -Limiting latency improves the user experience, and it can also help you avoid problems with data integrity, like [transaction contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +Limiting latency improves the user experience, and it can also help you avoid problems with data integrity, like [transaction contention](performance-best-practices-overview.html#transaction-contention). For the purpose of this tutorial, we'll focus on two types of latency: diff --git a/v21.2/operational-faqs.md b/v21.2/operational-faqs.md index bae1eb42b39..3032ec81782 100644 --- a/v21.2/operational-faqs.md +++ b/v21.2/operational-faqs.md @@ -120,7 +120,7 @@ In addition to using ballast files, it is important to actively [monitor remaini If queries operate on different data, then increasing the number of nodes should improve the overall throughput (transactions/second or QPS). -However, if your queries operate on the same data, you may be observing transaction contention. For details, see [SQL Performance Best Practices](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +However, if your queries operate on the same data, you may be observing transaction contention. For details, see [SQL Performance Best Practices](performance-best-practices-overview.html#transaction-contention). ## Why does CockroachDB collect anonymized cluster usage details by default? diff --git a/v21.2/performance-best-practices-overview.md b/v21.2/performance-best-practices-overview.md index 4ce59748024..5e3c8e9e7b1 100644 --- a/v21.2/performance-best-practices-overview.md +++ b/v21.2/performance-best-practices-overview.md @@ -6,14 +6,6 @@ toc: true This page provides best practices for optimizing query performance in CockroachDB. -{{site.data.alerts.callout_success}} -For deployment and data location techniques to minimize network latency in multi-region clusters, see [Topology Patterns](topology-patterns.html). -{{site.data.alerts.end}} - -{{site.data.alerts.callout_info}} -If you aren't sure whether SQL query performance needs to be improved on your cluster, see [Identify slow queries](query-behavior-troubleshooting.html#identify-slow-statements). -{{site.data.alerts.end}} - ## DML best practices ### Use multi-row statements instead of multiple single-row statements @@ -94,7 +86,7 @@ The best practices for generating unique IDs in a distributed database like Cock 1. Using the [`SERIAL`](serial.html) pseudo-type for a column to generate random unique IDs. This can result in a performance bottleneck because IDs generated temporally near each other have similar values and are located physically near each other in a table's storage. 2. Generating monotonically increasing [`INT`](int.html) IDs by using transactions with roundtrip [`SELECT`](select-clause.html)s, e.g., `INSERT INTO tbl (id, …) VALUES ((SELECT max(id)+1 FROM tbl), …)`. This has a **very high performance cost** since it makes all [`INSERT`](insert.html) transactions wait for their turn to insert the next ID. You should only do this if your application really does require strict ID ordering. In some cases, using [Change Data Capture (CDC)](stream-data-out-of-cockroachdb-using-changefeeds.html) can help avoid the requirement for strict ID ordering. If you can avoid the requirement for strict ID ordering, you can use one of the higher performance ID strategies outlined below. -The approaches described above are likely to create hotspots for both reads and writes in CockroachDB. To avoid this issue, we recommend the following approaches (listed in order from best to worst performance). +The approaches described above are likely to create hot spots for both reads and writes in CockroachDB. To avoid this issue, we recommend the following approaches (listed in order from best to worst performance). | Approach | Pros | Cons | |--------------------------------------------------------------------------------------+--------------------------------------------------+-----------------------------------------------------------------------------------------| @@ -106,7 +98,7 @@ The approaches described above are likely to create hotspots for both reads and A well-designed multi-column primary key can yield even better performance than a [UUID primary key](#use-uuid-to-generate-unique-ids), but it requires more up-front schema design work. To get the best performance, ensure that any monotonically increasing field is located **after** the first column of the primary key. When done right, such a composite primary key should result in: -- Enough randomness in your primary key to spread the table data / query load relatively evenly across the cluster, which will avoid hotspots. By "enough randomness" we mean that the prefix of the primary key should be relatively uniformly distributed over its domain. Its domain should have at least as many elements as you have nodes. +- Enough randomness in your primary key to spread the table data / query load relatively evenly across the cluster, which will avoid hot spots. By "enough randomness" we mean that the prefix of the primary key should be relatively uniformly distributed over its domain. Its domain should have at least as many elements as you have nodes. - A monotonically increasing column that is part of the primary key (and thus indexed) which is also useful in your queries. For example, consider a social media website. Social media posts are written by users, and on login the user's last 10 posts are displayed. A good choice for a primary key might be `(username, post_timestamp)`. For example: @@ -276,7 +268,7 @@ See [Subquery Performance Best Practices](subqueries.html#performance-best-pract See [Authorization Best Practices](authorization.html#authorization-best-practices). -## Table scans best practices +## Table scan best practices ### Avoid `SELECT *` for large tables @@ -323,53 +315,100 @@ If you have long-running queries (such as analytics queries that perform full ta However, because `AS OF SYSTEM TIME` returns historical data, your reads might be stale. -## Understanding and avoiding transaction contention +## Hot spots -Transaction contention occurs when the following three conditions are met: +Transactions that operate on the same range but _different index keys_ are limited by the overall hardware capacity of [the range lease holder](architecture/overview.html#terms) node. These are referred to as _hot spots_. -- There are multiple concurrent transactions or statements (sent by multiple clients connected simultaneously to a single CockroachDB cluster). -- They operate on the same data, specifically over table rows with the same index key values (either on [primary keys](primary-key.html) or secondary [indexes](indexes.html)) or using index key values that are close to each other, and thus place the indexed data on the same [data ranges](architecture/overview.html). -- At least one of the transactions modify the data. +Hot spots can occur when a range is indexed on a column of data that is sequential in nature such that all incoming writes to the range will be the last (or first) item in the index and appended to the end of the range. As a result, the system cannot find a point in the range that evenly divides the traffic, and the range cannot benefit from [load-based splitting](load-based-splitting.html), creating a hot spot on the single range. + +Read hot spots can occur if you perform lots of scans of an portion of a table index or a single key. + +### Find hot spots + +To track down the nodes experiencing hot spots, use the [hot ranges API endpoint](cluster-api.html#resources). + +### Reduce hot spots + +To reduce hot spots: + +- Use index keys with a random distribution of values, so that transactions over different rows are more likely to operate on separate data ranges. See the [SQL FAQs](sql-faqs.html#how-do-i-auto-generate-unique-row-ids-in-cockroachdb) on row IDs for suggestions. + +- Place parts of the records that are modified by different transactions in different tables. That is, increase [normalization](https://en.wikipedia.org/wiki/Database_normalization). However, there are benefits and drawbacks to increasing normalization. + + - Benefits: + - Allows separate transactions to modify related underlying data without causing contention. + - Can improve performance for read-heavy workloads. -A set of transactions that all contend on the same keys will be limited in performance to the maximum processing speed of a single node (limited horizontal scalability). Non-contended transactions are not affected in this way. + - Drawbacks: -There are two levels of contention: + - More complex data model. + - Increases the chance of data inconsistency. + - Increases data redundancy. + - Can degrade performance for write-heavy workloads. -- Transactions that operate on the same range but different index key values will be limited by the overall hardware capacity of a single node (the range lease holder). +- If the application strictly requires operating on very few different index keys, consider using [`ALTER ... SPLIT AT`](split-at.html) so that each index key can be served by a separate group of nodes in the cluster. -- Transactions that operate on the same index key values (specifically, that operate on the same [column family](column-families.html) for a given index key) will be more strictly serialized to obey transaction isolation semantics. +- If you are working with a table that *must* be indexed on sequential keys, use [hash-sharded indexes](hash-sharded-indexes.html). For details about the mechanics and performance improvements of hash-sharded indexes in CockroachDB, see the blog post [Hash Sharded Indexes Unlock Linear Scaling for Sequential Workloads](https://www.cockroachlabs.com/blog/hash-sharded-indexes-unlock-linear-scaling-for-sequential-workloads/). -Transaction contention can also increase the rate of transaction restarts, and thus make the proper implementation of [client-side transaction retries](transactions.html#client-side-intervention) more critical. +- To avoid read hot spots: -For further background on database contention, see [What is Database Contention, and Why Should You Care?](https://www.cockroachlabs.com/blog/what-is-database-contention/). + - Increase data distribution, which will allow for more ranges. The hot spot exists because the data being accessed is all co-located in one range. + - Increase load balancing across more nodes in the same range. Most transactional reads must go to the leaseholder in CockroachDB, which means that opportunities for load balancing over replicas are minimal. -### Find contention + However, the following features do permit load balancing over replicas: + + - Global tables + - Follower reads (both the bounded staleness and the exact staleness kinds) + + In these cases, more replicas will help, up to the number of nodes in the cluster. They all only help with reads, and they all come with their own tradeoffs. + + + +## Transaction contention + +Transactions that operate on the _same index key values_ (specifically, that operate on the same [column family](column-families.html) for a given index key) are strictly serialized to obey transaction isolation semantics. To maintain this isolation, writing transactions "lock" rows to prevent hazardous interactions with concurrent transactions. However, locking can lead to processing delays if multiple transactions are trying to access the same "locked" data at the same time. This is referred to as _transaction_ (or _lock_) _contention_. + +Transaction contention occurs when the following three conditions are met: + +- There are multiple concurrent transactions or statements (sent by multiple clients connected simultaneously to a single CockroachDB cluster). +- They operate on table rows with the _same index key values_ (either on [primary keys](primary-key.html) or secondary [indexes](indexes.html). +- At least one of the transactions modify the data. + +Transactions that experience contention typically show delays in completion or restarts. The possibility of transaction restarts requires clients to implement [transaction retries](transactions.html#client-side-intervention). + +For further background on transaction contention, see [What is Database Contention, and Why Should You Care?](https://www.cockroachlabs.com/blog/what-is-database-contention/). + +### Find transaction contention {% include {{ page.version.version }}/performance/statement-contention.md %} -### Avoid contention + -To avoid contention, you can apply multiple strategies: +### Reduce transaction contention -- Use index key values with a more random distribution of values, so that transactions over different rows are more likely to operate on separate data ranges. See the [SQL FAQs](sql-faqs.html) on row IDs for suggestions. +To reduce transaction contention: -- Make transactions smaller, so that each transaction has less work to do. In particular, avoid multiple client-server exchanges per transaction. For example, use [common table expressions](common-table-expressions.html) to group multiple [`SELECT`](select-clause.html) and [`INSERT`](insert.html)/[`UPDATE`](update.html)/[`DELETE`](delete.html)/[`UPSERT`](upsert.html) clauses together in a single SQL statement. +- Make transactions smaller, so that each transaction has less work to do. In particular, avoid multiple client-server exchanges per transaction. For example, use [common table expressions](common-table-expressions.html) to group multiple [`SELECT`](select-clause.html) and [`INSERT`](insert.html), [`UPDATE`](update.html), [`DELETE`](delete.html), and [`UPSERT`](upsert.html) clauses together in a single SQL statement. - For an example showing how to break up large transactions in an application, see [Break up large transactions into smaller units of work](build-a-python-app-with-cockroachdb-sqlalchemy.html#break-up-large-transactions-into-smaller-units-of-work). - If you are experiencing contention (retries) when doing bulk deletes, see [Bulk-delete data](bulk-delete-data.html). -- In combination with the above, if you are able to [send all of the statements in your transaction in a single batch](transactions.html#batched-statements), CockroachDB can automatically retry the transaction for you. +- [Send all of the statements in your transaction in a single batch](transactions.html#batched-statements) so that CockroachDB can automatically retry the transaction for you. -- Use the [`SELECT FOR UPDATE`](select-for-update.html) statement in scenarios where a transaction performs a read and then updates the row(s) it just read. It orders transactions by controlling concurrent access to one or more rows of a table. It works by locking the rows returned by a [selection query](selection-queries.html), such that other transactions trying to access those rows are forced to wait for the transaction that locked the rows to finish. These other transactions are effectively put into a queue that is ordered based on when they try to read the value of the locked row(s). +- Use the [`SELECT FOR UPDATE`](select-for-update.html) statement in scenarios where a transaction performs a read and then updates the row(s) it just read. The statement orders transactions by controlling concurrent access to one or more rows of a table. It works by locking the rows returned by a [selection query](selection-queries.html), such that other transactions trying to access those rows are forced to wait for the transaction that locked the rows to finish. These other transactions are effectively put into a queue that is ordered based on when they try to read the value of the locked row(s). - When replacing values in a row, use [`UPSERT`](upsert.html) and specify values for all columns in the inserted rows. This will usually have the best performance under contention, compared to combinations of [`SELECT`](select-clause.html), [`INSERT`](insert.html), and [`UPDATE`](update.html). -- Increase [normalization](https://en.wikipedia.org/wiki/Database_normalization) of the data to place parts of the same records that are modified by different transactions in different tables. Fully normalized data allows separate transactions to modify related underlying data without causing contention. Increasing normalization has drawbacks as well as benefits, however. Denormalizing data can increase performance for certain queries by creating multiple copies of often-referenced data in separate ranges, so read-heavy workloads may have higher performance. However, denormalization adds complexity the data model, increases the chance of data inconsistency, increases data redundancy, and can have poor performance when running write-heavy workloads. +### Improve transaction performance by sizing and configuring the cluster -- If the application strictly requires operating on very few different index key values, consider using [`ALTER ... SPLIT AT`](split-at.html) so that each index key value can be served by a separate group of nodes in the cluster. - -It is always best to avoid contention as much as possible via the design of the schema and application. However, sometimes contention is unavoidable. To maximize performance in the presence of contention, you'll need to maximize the performance of a single range. To achieve this, you can apply multiple strategies: +To maximize transaction performance, you'll need to maximize the performance of a single range. To achieve this, you can apply multiple strategies: - Minimize the network distance between the replicas of a range, possibly using zone configs and partitioning. - Use the fastest storage devices available. -- If the contending transactions operate on different keys within the same range, add more CPU power (more cores) per node. However, if the transactions all operate on the same key, this may not provide an improvement . +- If the contending transactions operate on different keys within the same range, add more CPU power (more cores) per node. However, if the transactions all operate on the same key, this may not provide an improvement. + +## See also + +If you aren't sure whether SQL query performance needs to be improved on your cluster, see [Identify slow queries](query-behavior-troubleshooting.html#identify-slow-statements). + +For deployment and data location techniques to minimize network latency in multi-region clusters, see [Topology Patterns](topology-patterns.html). diff --git a/v21.2/performance-recipes.md b/v21.2/performance-recipes.md index 9d59d06edd2..db63ff13f08 100644 --- a/v21.2/performance-recipes.md +++ b/v21.2/performance-recipes.md @@ -34,8 +34,8 @@ This section describes how to use CockroachDB commands and dashboards to identif
  • The SQL Statement Errors graph in the DB Console is showing spikes in retries over time.
  • - - + +