TPC-C
トランザクション処理性能評議会(Transaction processing Performance Council, TPC)の定める #ベンチマーク のひとつ. 物流システムを模したベンチマークになっている.ただし,
TPC-C does not represent the activity of any particular business segment, but rather any industry which must
manage, sell, or distribute a product or service (e.g., car rental, food distribution, parts supplie r, etc.)
とあるように特定の業態を想定はしない.物流系システムあるあるな設計を志向しているということだろうか.
ユーザが操作可能な変数(scale factorと呼ばれている)は一つ. warehouse すなわち倉庫数.
warehouseは(物流会社の倉庫なので)地理的に分散しており,1 < warehouse であれば,warehouse越しのトランザクションはネットワークを介して行う分散トランザクションとなる. スキーマ
https://gyazo.com/fa37ee7ad777176a93df3ae90bade25a
以下がRDBMSでいうところのテーブル.
warehouse: 倉庫(拠点)数.ユーザが決定できる.$ wとする
district: 倉庫が担当する配送区画の数.各倉庫に10区画.$ d= w*10画.
customer: 配送先となる消費者.各区画に3000人. $ c = d*3000人.
3000だった
item: 商品.各倉庫に100,000件.
stock: 各商品の在庫情報.itemに紐づく.
comapny: 会社.1件.item を管理している.
order: 発注. 1件の注文あたり10件の order_lineを持つ.発注者としてcustomerの情報を持つ.
new_orderなのかexisting_orderつまり取引済みなのか区別できないといけない.
厳密に正規化すると別のテーブルになる.
order_line: 注文明細.item のIDを持つ.
重要な要件として,全体のorder_lineのうち1%はRemote Warehouseのitemを対象としていなければならない.
Remoteとは: order_line.order.customer.district.warehouse !== order_line.item.warehouseのこと
まれには他の倉庫からのお取り寄せになる,ということ.
history: 支払い情報.customerの情報を持つ.
つまり,だいたい以下のスケールでデータベースを初期化する.
https://gyazo.com/b4095f8e730b89042ec00f980ad48fbe
データ型
ID: ユニークな識別子.実装は数値でも文字列でもバイナリでも何でもよし.
variable text: 可変長文字列.最大サイズ$ Nを宣言時に与え,その長さ分のメモリ領域を確保する.
つまり実質固定長のように扱えるじゃん
fixed text: 固定長文字列.文字列サイズ$ Nを確保する.
date and time: 時間.どのような実装・表現でも良いが,以下を要件とする
1900/1/1から2100/12/31までは表現できること.
また,範囲検索ができること.
numeric(m,n): (unsignedな)数値.合計$ m桁で,$ n桁は小数点以下..
signed numeric(m,n): 符号付き数値.
null
スキーマの詳細
WAREHOUSE
code:warehouse.rb
Field Name Field Definition Comments
W_ID 2*W unique IDs W Warehouses are populated
W_NAME variable text, size 10
W_STREET_1 variable text, size 20
W_STREET_2 variable text, size 20
W_CITY variable text, size 20
W_STATE fixed text, size 2
W_ZIP fixed text, size 9
W_TAX signed numeric(4,4) Sales tax
W_YTD signed numeric(12,2) Year to date balance
Primary Key: W_ID
DISTRICT
code:district.rb
Field Name Field Definition Comments
D_ID 20 unique IDs 10 are populated per warehouse
D_W_ID 2*W unique IDs
D_NAME variable text, size 10
D_STREET_1 variable text, size 20
D_STREET_2 variable text, size 20
D_CITY variable text, size 20
D_STATE fixed text, size 2
D_ZIP fixed text, size 9
D_TAX signed numeric(4,4) Sales tax
D_YTD signed numeric(12,2) Year to date balance
D_NEXT_O_ID 10,000,000 unique IDs Next available Order number
Primary Key: (D_W_ID, D_ID)
D_W_ID Foreign Key, references W_ID
CUSTOMER
code: customer.rb
Field Name Field Definition Comments
C_ID 96,000 unique IDs 3,000 are populated per district
C_D_ID 20 unique IDs
C_W_ID 2*W unique IDs
C_FIRST variable text, size 16
C_MIDDLE fixed text, size 2
C_LAST variable text, size 16
C_STREET_1 variable text, size 20
C_STREET_2 variable text, size 20
C_CITY variable text, size 20
C_STATE fixed text, size 2
C_ZIP fixed text, size 9
C_PHONE fixed text, size 16
C_SINCE date and time
C_CREDIT fixed text, size 2 "GC"=good, "BC"=bad
C_CREDIT_LIM signed numeric(12, 2)
C_DISCOUNT signed numeric(4, 4)
C_BALANCE signed numeric(12, 2)
C_YTD_PAYMENT signed numeric(12, 2)
C_PAYMENT_CNT numeric(4)
C_DELIVERY_CNT numeric(4)
C_DATA variable text, size 500 Miscellaneous information
Primary Key: (C_W_ID, C_D_ID, C_ID)
(C_W_ID, C_D_ID) Foreign Key, references (D_W_ID, D_ID)
C_LAST の生成ルールはちょっと面倒.0~999の乱数を生成し,それに応じて文字列を生成する
HISTORY
code:history.rb
Field Name Field Definition Comments
H_C_ID 96,000 unique IDs
H_C_D_ID 20 unique IDs
H_C_W_ID 2*W unique IDs
H_D_ID 20 unique IDs
H_W_ID 2*W unique IDs
H_DATE date and time
H_AMOUNT signed numeric(6, 2)
H_DATA variable text, size 24 Miscellaneous information
Primary Key: none
(H_C_W_ID, H_C_D_ID, H_C_ID) Foreign Key, references (C_W_ID, C_D_ID, C_ID)
(H_W_ID, H_D_ID) Foreign Key, references (D_W_ID, D_ID)
注意書き:
Comment: Rows in the History table do not have a primary key as, within the context of the benchmark, there is no need to uniquely identify a row within this table.
Note: The TPC-C application does not have to be capable of utilizing the increased range of C_ID values beyond 6,000.
NEW-ORDER
code:neworder.rb
Field Name Field Definition Comments
NO_O_ID 10,000,000 unique IDs
NO_D_ID 20 unique IDs
NO_W_ID 2*W unique IDs
Primary Key: (NO_W_ID, NO_D_ID, NO_O_ID)
(NO_W_ID, NO_D_ID, NO_O_ID) Foreign Key, references (O_W_ID, O_D_ID, O_ID)
ORDER
code: order.rb
Field Name Field Definition Comments
O_ID 10,000,000 unique IDs
O_D_ID 20 unique IDs
O_W_ID 2*W unique IDs
O_C_ID 96,000 unique IDs
O_ENTRY_D date and time
O_CARRIER_ID 10 unique IDs, or null
O_OL_CNT numeric(2) Count of Order-Lines
O_ALL_LOCAL numeric(1)
Primary Key: (O_W_ID, O_D_ID, O_ID)
(O_W_ID, O_D_ID, O_C_ID) Foreign Key, references (C_W_ID, C_D_ID, C_ID)
ORDER-LINE
code:order-line.rb
Field Name Field Definition Comments
OL_O_ID 10,000,000 unique IDs
OL_D_ID 20 unique IDs
OL_W_ID 2*W unique IDs
OL_NUMBER 15 unique IDs
OL_I_ID 200,000 unique IDs
OL_SUPPLY_W_ID 2*W unique IDs
OL_DELIVERY_D date and time, or null
OL_QUANTITY numeric(2)
OL_AMOUNT signed numeric(6, 2)
OL_DIST_INFO fixed text, size 24
Primary Key: (OL_W_ID, OL_D_ID, OL_O_ID, OL_NUMBER)
(OL_W_ID, OL_D_ID, OL_O_ID) Foreign Key, references (O_W_ID, O_D_ID, O_ID)
(OL_SUPPLY_W_ID, OL_I_ID) Foreign Key, references (S_W_ID, S_I_ID)
ITEM
code:item.rb
Field Name Field Definition Comments
I_ID 200,000 unique IDs 100,000 items are populated
I_IM_ID 200,000 unique IDs Image ID associated to Item
I_NAME variable text, size 24
I_PRICE numeric(5, 2)
I_DATA variable text, size 50 Brand information
Primary Key: I_ID
STOCK
code:stocktable.rb
Field Name Field Definition Comments
S_I_ID 200,000 unique IDs 100,000 populated per warehouse
S_W_ID 2*W unique IDs
S_QUANTITY signed numeric(4)
S_DIST_01 fixed text, size 24
S_DIST_02 fixed text, size 24
S_DIST_03 fixed text, size 24
S_DIST_04 fixed text, size 24
S_DIST_05 fixed text, size 24
S_DIST_06 fixed text, size 24
S_DIST_07 fixed text, size 24
S_DIST_08 fixed text, size 24
S_DIST_09 fixed text, size 24
S_DIST_10 fixed text, size 24
S_YTD numeric(8)
S_ORDER_CNT numeric(4)
S_REMOTE_CNT numeric(4)
S_DATA variable text, size 50 Make information
Primary Key: (S_W_ID, S_I_ID)
S_W_ID Foreign Key, references W_ID
S_I_ID Foreign Key, references I_ID
以上のスキーマで,5つのトランザクションを実行する.
NewOrder:
Payment:
OrderStatus
Delivery
StockLevel
ベンチマークに用いる指標としては,「あるmesuarement interval 中にcommitしたトランザクションの数を数える. それぞれをどのような割合で実行するか,ということについては5.2.5.7に記述がある.
https://gyazo.com/419268fc38726f4658f2b023d1e762dc
具体的には,Transaction Typeごとに上から 10:10:1:1:1 の比率で実行しろ,ということらしい.
メモ
ここから,実装上のポイントとDBに対する要件について記述がある.
ようするに読み進めた上でのメモ.
DBなら当たり前では・・・?という項目もあり,いかにルールをかいくぐられてきたかが窺い知れる.
たとえば, TPC-Cでは,具体的には,ユーザとのインタラクションも含めて要件に入っていて,
https://gyazo.com/8614ed3170ecb79363b606f32f14de01
このようなループを実行しなければならない.
ユーザがクエリを入力する時間や,考える時間をsleepでemulationしろと書いてある.
こういう要件などは読み飛ばしてゆっくり読んでいる.そのメモを以下に置く.
Implementation Rules
1.4.1 The physical clustering of records within the database is allowed.
クラスタリング∋パーティション,シャーディング?
1.4.2 A view which represents the rows to avoid logical read/ writes is excluded
ビューの実装は許容しない.これを行うと,複数のクエリを一つにまとめることができてしまう. 1.4.4-1.4.6
パーティションは許容する.
シャーディングも許容する.
レプリケーションも許容する.ただしACID特性を満たすこと. 1.4.7: 性能が向上しないなら,各テーブルのattributesを足してもいい.複製してもいい.
1.4.8-1.4.9 ただしattributesのマージ/分割は禁止.W_STREET(W_STREET_1 + W_STREET2) のような表現もその逆もダメ.
1.4.10 は複数の項目が書かれている
Primary Keyはディスク上の物理アドレスであってはいけない.
その発想なかった...
オフセットの数値も禁止.各行のPrimary Keyがオフセットで,ストレージからの相対位置アクセス...はNG
HashをかけるとかすればOK.ようするに「インデックス無しで配列にする」とかは現実的じゃないのでNG
History Tableに限っては,配列に詰めていくといった処理を許容する.
1.4.11 InsertとDeleteが全てのテーブルで行われるわけではないことを逆手にとってはいけない.
各テーブルの現在の行数の5%に相当する追加Insertや,2倍のPrimary Key(?)を追加することが出来る状態にすること.
要するにストレージレイアウトを最適化して綺麗に詰め込むのはダメ
1.4.12 小数点数の計算は,システム上可能な最大限の精度で行う.
1.4.13 この文書中に他にもルールがあります. 3章とか.
えぇ・・・
1.4.14 データ型はDBのnative型として実装されていなければならない.
datetimeが無いからstringで格納して後でパースします,というのはNG.
Integrity Rules
1.5.1 CommittedなタプルのPrimary KeyはUniqueでなければならない.
1.5.2 Committedなタプルは全てのattributesに一貫性を持ってアクセスできなければならない.
あるattributeだけ,更新が遅れている,ということは起こってはいけない.
1.6 Data Access Transparency Requirements
1.6.1 テーブル名は先ほど述べた9つのものを使う.アプリケーションは必ずこれを使う.
1.6.2 TPC-C外のアプリケーションからもIntegrity Rulesが守られなければならない.
たとえば,non-TPC-Cによる特定のPartitionに置いたattributeの更新と,TPC-Cの全attributesの更新がかちあうなど.
1.6.3 non-TPC-Cのアプリケーションも各テーブル/各行を更新できなければならない.
要するに,汎用的に運用できるデータベースじゃないといけない.
この時点で論文などのリファレンス実装は脱落かな・・・
2.1 Definition of terms
select や retrieve , random といった単語の定義.省略
2.2 General Requirements for Terminal I/O
Terminalを用いて入出力を行うので,そこにも制約がある.
(これはTPCの審査員のための要件かな)
言語は何でもよいとか,しかしカラム名などは翻訳禁止である,とか,そういった話が書かれている.
Webブラウザから入出力をやる場合はechoコマンドのレスポンスタイムが1秒以内であること,とか.
全てのトランザクションが以下のような表示をする必要がある.
https://gyazo.com/5da7076e5acee80ac00a672df1dd3bc9
2.3 General Requirements for Transaction Profiles
各トランザクションについての要件,ならびに,トランザクションモニタ(TM)についての要件.
これも審査向けの話が多い.
要件を満たす限り,1トランザクション内での各処理の実行順は問題ではない.
FILTERしてJOINのところを,先にJOINしてFILTERする,というのも,どちらもOK
基本的に計算量が最小となるように検索/.更新する.追加の処理をする場合はユーザにその目的を示す.
エラーの情報が見れなければならない
など.
Queries
ここからTPC-Cの5つのクエリの解説が入る.
The New-Order
TPC-Cで最も有名なクエリ.商品の発注を行う.
クエリは以下のように作成する.
the home warehouse number (W_ID) はトランザクション中の定数.
the district number(D_ID) をwarehouseの中からランダムに決める.つまりrand([0..9]).
customer number(C_ID) を非一様乱数で決める.NURand(1023, 1, 3000)のような感じ
NURand(A, x, y) = (((random(0, A) | random(x, y)) + C) % (y - x + 1)) + x
random(x, y) stands for randomly selected within x .. y A is a constant chosen according to the size of the range x .. y C is a run-time constant randomly chosen within 0 .. A that can be varied without altering performance. 何で3000...? 1districtあたりcustomerは1000人のはずだが...
the number of items in the order(ol_cnt) は5~15からランダムに決定.
rbk フィールドに1..100の乱数を入力し,1%の注文は入力エラーなりでロールバックさせる.
for each in 0..ol_cnt で
商品ID(OL_I_ID)を決定する.NURand(8191,1,100000)を使う
在庫がない場合はabortする.
倉庫ID(OL_SUPPLY_W_ID)を決定する.[1..100]で乱数を引き,1%でremote warehouseにする.
一回のOrderあたり平均10件のItemを発注していて,Itemは1%の確率でremoteなので,10% remoteということになる.
商品の数量(OL_QUANTITY) を[1..10]でランダムに決める.
日付(O_ENTRY_D)は現在のシステム時間を使う
処理全体で以下の検索と更新がある.
1. Create an order header, comprised of:
2 row selections with data retrieval,
1 row selection with data retrieval and update,
2 row insertions.
2. Order a variable number of items (average ol_cnt = 10), comprised of:
(1 * ol_cnt) row selections with data retrieval,
(1 * ol_cnt) row selections with data retrieval and update,
(1 * ol_cnt) row insertions.
流れは以下.
前述のようにクエリを作る.
トランザクションを開始する.
NO_W_IDを使いwarehouseテーブルからレコードを引き,W_TAXフィールドをselectして税率を得る.
NO_D_IDを使いdistrictテーブルからレコードを引く.D_TAXフィールドをselectして税率を引く
D_NEXT_O_IDを更新して,次に処理する注文を自分にする.
NO_C_IDを使いcustomerテーブルからレコードを引く.C_DISCOUNTフィールドは割引率.
NEW_ORDERテーブルに新しいレコードを作成する.
O_CARRIER_ID はNULL.
O_ALL_LOCAL はremoteがある場合は0. それ以外は1.
ORDERテーブルにももちろん作る.
各Item(OrderLine)ごとに以下の処理をする.
OL_I_IDを使いItemテーブルからレコードを引く.
OL_I_IDを使いStockテーブルから在庫量を引く.
OrderLineの新しいレコードを作成する.
OL_DELIVERY_Dはnull
OL_NUMBERは同じOrder内でunique
TOTAL_AMOUNT つまり合計金額は以下の計算に従う
sum(OL_AMOUNT) * (1 - C_DISCOUNT) * (1 + W_TAX + D_TAX)
code: sql
SELECT FROM warehouse JOIN customer;
SELECT FROM district FOR UPDATE;
UPDATE district;
INSERT INTO orders;
INSERT INTO new_orders;
LOOP {
SELECT FROM item;
SELECT FROM stock FOR UPDATE;
UPDATE stock;
INSERT INTO order_line;
}
COMMIT;