Professional Documents
Culture Documents
Phil Hildebrand
phil.hildebrand@gmail.com
•Implementation examples
Q&A
Classic Partitioning
Old School – union in the archive tables
Design Issues
•Often id driven access vs. date driven access
Operational Issues
•Difficult to schedule downtime for DDL changes
+---+-------------+-----------------+------------+-------+---------------+---------+---------+------+-------+--------------------------------+
|id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+---+-------------+-----------------+------------+-------+---------------+---------+---------+------+-------+--------------------------------+
| 1 | SIMPLE | my_store | p5,p8,p10 | range | PRIMARY | PRIMARY | 8 | NULL | 3 | Using where |
| 1 | SIMPLE | my_employee_old | NULL | ALL | NULL | NULL | NULL | NULL | 47483 | Using where; Using join buffer |
+_--+-------------+-----------------+------------+-------+---------------+---------+---------+------+-------+--------------------------------+
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------------+
| 1 | SIMPLE | my_store | p5,p8,p10 | range | PRIMARY | PRIMARY | 8 | NULL | 3 | Using where |
| 1 | SIMPLE | my_employee | p5,p8,p10 | ALL | NULL | NULL | NULL | NULL | 2979 | Using where; Using join buffer |
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------------+
Simple join with out partitions
Benchmark
Average number of seconds to run all queries: 0.141 seconds
Minimum number of seconds to run all queries: 0.101 seconds
Maximum number of seconds to run all queries: 0.213 seconds
Number of clients running queries: 5
Average number of queries per client: 1
real 2m22.018s
user 0m0.217s
sys 0m0.445s
Simple join with partitions
Benchmark
Average number of seconds to run all queries: 0.006 seconds
Minimum number of seconds to run all queries: 0.005 seconds
Maximum number of seconds to run all queries: 0.025 seconds
Number of clients running queries: 5
Average number of queries per client: 1
real 0m6.660s
user 0m0.133s
sys 0m0.306s
Rebuilding by partition
mysql> optimize table my_employee_old;
+----------------------+----------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------+----------+----------+----------+
| conf.my_employee_old | optimize | status | OK |
+----------------------+----------+----------+----------+
1 row in set (1.14 sec)
Design Considerations
•Table sizes and predicted growth patterns
•Access patterns
•Keys and indexes
•Availability and Scalability requirements
•Manageability considerations
•Reuse considerations
Choosing a Partitioning Method
Range Partitioning
•Data usually accessed by date
•Limited number of (primary) partitions needed
•Ordered Intelligent keys
•Supports Sub Partitions
List Partitioning
•Grouping data in partitions out of order (1,5,7 in partition x)
•Limited number of (primary) partitions needed
•Intelligent keys
•Supports Sub Partitions
Hash Partitioning
•Low maintenance
•Works with limited or large number of partitions
•Non-intelligent keys (can work with some cases of intelligent keys)
Key Partitioning
•Non-integer based partitioned keys (md5 hash)
•Low maintenance
Hash Partitioning and OLTP
mysql> show columns from my_store; mysql> show columns from my_inventory;
+---------+--------------+------+-----+---------+ +----------+-------------+------+-----+---------+
| Field | Type | Null | Key | Default | | Field | Type | Null | Key | Default |
+---------+--------------+------+-----+---------+ +----------+-------------+------+-----+---------+
| id | bigint(20) | NO | PRI | NULL | | id | bigint(20) | NO | PRI | NULL |
| city | varchar(128) | YES | | NULL | | store_id | bigint(20) | NO | PRI | NULL |
| country | varchar(128) | YES | | NULL | | name | varchar(56) | YES | | NULL |
+---------+--------------+------+-----+---------+ | in_stock | bit(1) | YES | | NULL |
| on_order | bit(1) | YES | | NULL |
| item_cnt | bigint(20) | YES | | NULL |
mysql> show columns from my_employee;
| cost | float | YES | | NULL |
+----------+-------------+------+-----+---------+
+----------+-------------+------+-----+---------+
| Field | Type | Null | Key | Default |
+----------+-------------+------+-----+---------+
| id | bigint(20) | NO | PRI | NULL |
| store_id | bigint(20) | NO | PRI | NULL |
| name | varchar(56) | YES | | NULL |
+----------+-------------+------+-----+---------+
Applying Hash Partitioning
Partition on Store ID
mysql> ALTER TABLE MY_STORE PARTITION BY HASH (id) PARTITIONS 50 ;
Query OK, 50 rows affected (0.76 sec)
Records: 50 Duplicates: 0 Warnings: 0
+--------------+----------+
| table_name | count(*) |
+--------------+----------+
| my_employee | 48 |
| my_inventory | 48 |
| my_store | 48 |
+--------------+----------+
A Few More Stats… (No Partitions)
mysql> explain partitions select my_store_no_part.city,my_employee_no_part.name,count(*) from
my_store_no_part, my_employee_no_part, my_inventory_no_part where my_store_no_part.id in (5,8,10,23,80)
and my_store_no_part.id = my_employee_no_part.store_id and my_store_no_part.id =
my_inventory_no_part.store_id and my_employee_no_part.id < 2000 and my_inventory_no_part.in_stock =
(ROUND(RAND(),0)) group by my_store_no_part.city,my_employee_no_part.name;
+---+-------------+----------------------+------------+--------+---------------+---------+---------+-----------------------------------
+--------+----------------------------------------------+
|id | select_type | table | partitions | type | possible_keys | key | ref
| rows | Extra |
+---+-------------+----------------------+------------+--------+---------------+---------+---------+-----------------------------------
+--------+----------------------------------------------+
| 1 | SIMPLE | my_employee_no_part | NULL | range | PRIMARY | PRIMARY | NULL |
3962 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | my_store_no_part | NULL | eq_ref | PRIMARY | PRIMARY |
conf.my_employee_no_part.store_id | 1| |
| 1 | SIMPLE | my_inventory_no_part | NULL | ALL | NULL | NULL | NULL |
508243 | Using where; Using join buffer |
+----+-------------+----------------------+------------+--------+---------------+---------+---------+-----------------------------------
+--------+----------------------------------------------+
mysql> select my_store_no_part.city,my_employee_no_part.name,count(*) from my_store_no_part,
my_employee_no_part, my_inventory_no_part where my_store_no_part.id in (5,8,10,23,80) and
my_store_no_part.id = my_employee_no_part.store_id and my_store_no_part.id =
my_inventory_no_part.store_id and my_employee_no_part.id < 2000 and my_inventory_no_part.in_stock =
(ROUND(RAND(),0)) group by my_store_no_part.city,my_employee_no_part.name;
+----------+-------------+----------+
| city | name | count(*) |
+----------+-------------+----------+
| Delhi | Employee #0 | 60453 |
| Istanbul | Employee #0 | 79707 |
| Karachi | Employee #0 | 59872 |
A Few More Stats… (Partitions)
mysql> explain partitions select my_store_lrg.city,my_employee_lrg.name,count(*) from my_store_lrg,
my_employee_lrg, my_inventory_lrg where my_store_lrg.id in (5,8,10,23,80) and my_store_lrg.id =
my_employee_lrg.store_id and my_store_lrg.id = my_inventory_lrg.store_id and my_employee_lrg.id < 2000
and my_inventory_lrg.in_stock = (ROUND(RAND(),0)) group by my_store_lrg.city,my_employee_lrg.name;
+---+-------------+------------------+-------------------+--------+---------------+---------+---------+-------------------------------+-------
+----------------------------------------------+
|id | select_type | table | partitions | type | possible_keys | key | ref |
rows | Extra |
+---+-------------+------------------+-------------------+--------+---------------+---------+---------+-------------------------------+-------
+----------------------------------------------+
|1 | SIMPLE | my_employee_lrg | p5,p8,p10,p23,p80 | range | PRIMARY | PRIMARY | NULL |
94 | Using where; Using temporary; Using filesort |
|1 | SIMPLE | my_store_lrg | p5,p8,p10,p23,p80 | eq_ref | PRIMARY | PRIMARY |
conf.my_employee_lrg.store_id | 1| |
|1 | SIMPLE | my_inventory_lrg | p5,p8,p10,p23,p80 | ALL | NULL | NULL | NULL |
47938 | Using where; Using join buffer |
+----+-------------+------------------+-------------------+--------+---------------+---------+---------+-------------------------------
+-------+----------------------------------------------+