This section discusses how to partition a database to maximize throughput, using the flight reservation case study as an example. To partition a table, you choose a column of the table that VoltDB can use to uniquely identify and distribute the rows into partitions. The goal of partitioning a database table is to ensure that the most frequent transactions on the table execute in the same partition as the data accessed. We call this a single-partitioned transaction. Thus the stored procedure must uniquely identify a row by the partitioning column value. This is particularly important for queries that modify the data, such as INSERT, UPDATE, and DELETE statements.
Looking at the workload for the reservation system in the previous section, the important transactions to focus on are:
Look up a flight
See if a flight is available
Look up a reservation
Make a reservation
Of these transactions, only the last modifies the database.
We will discuss the Flight table later, but first let's look at the Reservation table. Looking at the schema alone (Example 4.1), ReserveID might look like a good attribute to use to partition the table rows. However, looking at the workload, there are only two transactions that are keyed to the ReserveID (“Cancel a reservation” and “Look up a reservation (by reservation ID)”), each of which occur only 200 times a second. Whereas, “See if a flight is available” , which requires looking up reservations by the FlightID, occurs 5,000 times a second, or 25 times as frequently. Therefore, the Reservation table is best partitioned on the FlightID column.
Moving to the Customer table, CustomerID is used for most data access. Although customers might need to look up their record by name, the first and last names are not guaranteed to be unique. Therefore, CustomerID is the best column to use for partitioning the Customer table.
CREATE TABLE Customer ( CustomerID INTEGER UNIQUE NOT NULL, FirstName VARCHAR(15), LastName VARCHAR (15), PRIMARY KEY(CustomerID) );
Once you choose the column to use for partitioning a database table, you define your partitioning choices in the database schema. Specifying the partitioning along with the schema DDL helps keep all of the database structural information in one place.
You define the partitioning scheme using VoltDB's PARTITION TABLE statement, specifying the partitioning column for each table. For example, to specify FlightID and CustomerID as the partitioning columns for the Reservation and Customer tables, respectively, your database schema must include the following statements:
$ sqlcmd 1> PARTITION TABLE Reservation ON COLUMN FlightID; 2> PARTITION TABLE Customer ON COLUMN CustomerID;
The following are the rules to keep in mind when choosing a column by which to partition table rows:
There can be only one partition column per table. If you need to partition a table on two columns (for example first and last name), add an additional column (fullname) that combines the values of the two columns and use this new column to partition the table.
If the table has a primary key, the partitioning column must be included in the primary key.
Any integer, string, or byte array column can identify the partition. VoltDB can partition rows on any column that is an integer (TINYINT, SMALLINT, INTEGER, or BIGINT), string (VARCHAR), or byte array (VARBINARY) datatype. (See also Table A.1, “Supported SQL Datatypes”.)
Partition column values cannot be null. The partition columns do not need to have unique values, but you must specify NOT NULL in the schema for the partition column. Numeric fields can be zero and string or character fields can be empty, but the column cannot contain a null value.
The following are some additional recommendations:
Choose a column with a reasonable distribution of values so that rows of data will be evenly partitioned.
Choose a column that maximizes use of single-partitioned stored procedures. If one procedure uses column A to lookup data and two procedures use column B to lookup data, partition on column B. The goal of partitioning is to make the most frequent transactions single-partitioned.
If you partition more than one table on the same column attribute, VoltDB will partition them together.