
Core Issue | Scenario Without Partitioning | How Partitioning Addresses the Issue |
Where is the data? | All data is piled up on a single node, while other nodes remain idle. | Evenly distributing to all nodes according to rules |
Where to route queries | Each SQL query must be sent to all nodes. | Queries with partition keys are directly routed to a single node. |
How to eliminate hotspots | New data is written to a single node in a centralized manner. | Hashing to scatter data and evenly distributing writes |

-- ❌ Error: A PRIMARY KEY must include all columns in the table's partitioning functionCREATE TABLE users (id BIGINT PRIMARY KEY,userid BIGINT) PARTITION BY HASH(userid) PARTITIONS 16;-- ✅ Correct: The primary key includes the partition keyCREATE TABLE users (id BIGINT AUTO_INCREMENT,userid BIGINT NOT NULL,PRIMARY KEY (userid)) PARTITION BY HASH(userid) PARTITIONS 16;

-- ❌ Write hotspot: new data is always written to the last partitionCREATE TABLE t (id BIGINT AUTO_INCREMENT,...PRIMARY KEY (id)) PARTITION BY RANGE(id) (PARTITION p0 VALUES LESS THAN (100000),PARTITION p1 VALUES LESS THAN (200000),PARTITION p_maxvalue VALUES LESS THAN MAXVALUE -- All new data resides here);-- ✅ RANGE manages the lifecycle by time + HASH distributes writes) PARTITION BY RANGE COLUMNS(created_at)SUBPARTITION BY HASH(userid) SUBPARTITIONS 6 (...);
-- ✅ Accesses only one node, with millisecond-level responseSELECT * FROM orders WHERE userid = 12345;-- ❌ Accesses all nodes, with each node being queried onceSELECT * FROM orders WHERE orderno = 'ORD-001';
Type | Principle | Scenarios | Example |
HASH | Evenly distributing data by performing modulo operations on integers | User tables, order tables, general business tables | PARTITION BY HASH(userid) |
KEY | Scattering data by performing internal hashing on any data type | Scenarios where the partition key is VARCHAR | PARTITION BY KEY(orderno) |
RANGE | Partitioning data based on value ranges | Log tables, transaction tables, tables that require time-based cleanup | PARTITION BY RANGE COLUMNS(created_at) |
RANGE + HASH | First partitioning by range, then scattering data at the second level | Large transaction tables: requiring time-based cleanup and distributed writes | |
Current Number of Nodes | Number of Nodes After Expected Scale-Out | Recommended Number of Partitions |
3 nodes | 6~8 | 16 |
6 nodes | 12 | 24 |
CREATE TABLE orders (...KEY idx_order_no (orderno) -- A LOCAL index that does not include the partition key userid) PARTITION BY HASH(userid) PARTITIONS 16;
SELECT * FROM orders WHERE orderno = 'ORD-2026-001';
Query method | Number of Partitions Accessed | Network RPC | Applicable Scenarios |
WHERE userid = X | 1 | 1 time | High-frequency queries |
WHERE orderno = X (LOCAL index) | All | N times | Low-frequency queries, small result sets |
Full table scan without index | All | N times | Never use. |
-- From thisSELECT * FROM orders WHERE orderno = 'ORD-001';-- Change to this (if the business logic can obtain the userid)SELECT * FROM orders WHERE userid = 123 AND orderno = 'ORD-001';
| Partitioning by user_id | Partitioning by order_no |
Query user order list | Single partition, naturally aggregated | Scattered across partitions |
Query a single order by order number | Using a LOCAL index, the query fans out to all partitions (acceptable as each partition contains at most one row). | Single partition |
Write uniformity | The user_id is an integer, resulting in effective HASH distribution. | Order numbers often contain date prefixes, which may lead to uneven hash distribution. |
Partition Type | HASH (integer) | KEY (string, HASH does not support VARCHAR) |
Standalone MySQL | TDSQL Boundless | Reason for Change |
id BIGINT AUTO_INCREMENT PRIMARY KEY | Using business keys as the primary key instead of auto-increment IDs. | Avoid write hotspots |
No Partitioning | Adding PARTITION BY HASH(business_key1, business_key2) | Distributing data across multiple nodes |
Cleaning up historical data with DELETE WHERE date < '...' | Using DROP PARTITION instead | Millisecond completion vs. table locked for hours |
Creating indexes arbitrarily | The index for core queries must include the partition key. | Avoiding full-partition scans |
-- Orders table, before transformation (MySQL)CREATE TABLE orders (id BIGINT AUTO_INCREMENT PRIMARY KEY,userid BIGINT,orderno VARCHAR(64),amount DECIMAL(10,2),status TINYINT,created_at DATETIME,KEY idx_order_no (orderno),KEY idx_created (created_at));-- Orders table, after transformation (TDSQL Boundless)CREATE TABLE orders (id BIGINT AUTO_INCREMENT,userid BIGINT NOT NULL,orderno VARCHAR(64) NOT NULL,amount DECIMAL(10,2),status TINYINT,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (userid, orderno), -- The partition key is the first column in the primary keyKEY idx_order_no (orderno), -- The order number index handles searches based on order number.KEY idx_user_created (userid, created_at) -- For user order list queries) PARTITION BY HASH(userid) PARTITIONS 16;
-- ✅ No modification required; it naturally hits the partition.SELECT * FROM orders WHERE userid = 123 ORDER BY created_at DESC LIMIT 20;SELECT * FROM orders WHERE userid = 123 ORDER BY orderno DESC LIMIT 20;
-- Optimal scenario: Query the order number with the user's userid.SELECT * FROM orders WHERE userid = 123 AND orderno = 'ORD-001';-- Acceptable (LOCAL index, 16 index lookups)SELECT * FROM orders WHERE orderno = 'ORD-001';
CREATE TABLE dim_city (city_id INT PRIMARY KEY,city_name VARCHAR(64)) sync_level = node(all) distribution = node(all);
Table Type | Use Cases | Feature |
Regular Table (Single Table) | Small data volume, no distribution requirement | All data resides within a single RG. |
Partition Table | Large data volume, requires horizontal scaling | Data is distributed across multiple service groups according to rules. |
Synchronization table | System configurations, dimension tables, parameter tables, small tables with more reads than writes | Strongly synchronized replicas across all nodes. Write operations may experience latency under frequent writes, for example, a Lease may be blocked when a Follower fails. |
-- With partition keyEXPLAIN SELECT * FROM orders WHERE userid = 12345;*************************** 1. row ***************************id: 1select_type: SIMPLEtable: orderspartitions: p1type: refpossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: constrows: 2filtered: 100.00Extra: NULL-- Without partition keyorders*************************** 1. row ***************************id: 1select_type: SIMPLEtable: orderspartitions: p0,p1,p2,p3,p4,p5,p6,p7type: refpossible_keys: idx_order_nokey: idx_order_nokey_len: 258ref: constrows: 9filtered: 100.00Extra: NULL
Incorrect Example | Impact | Correct Practices |
Using auto-increment ID as both primary key and partition key | Write hotspot | Use business fields as the partition key and primary key; when sorting is performed with order by, use business time or other naturally ordered fields for sorting. |
Querying without a partition key | Full-partition scan | Add the partition key to the WHERE clause. |
Updating the value of a partition key. | Cross-partition migration, may fail. | Using DELETE + INSERT instead of a direct UPDATE |
Using HASH partitioning for VARCHAR | Table creation error | Use KEY partitioning. |
Using RANGE partitioning by day and retaining data for multiple years | 1000+ partitions, metadata bloat | Change to monthly partitioning (36 partitions/3 years). |
Esta página foi útil?
Você também pode entrar em contato com a Equipe de vendas ou Enviar um tíquete em caso de ajuda.
comentários