From aa1f59e3440994543ed704ef05decde58859bf5a Mon Sep 17 00:00:00 2001 From: Richard Yao <2501.owlsome@gmail.com> Date: Wed, 5 Nov 2025 19:26:30 +0800 Subject: [PATCH] tpcc: set clustered_index as optional --- cmd/go-tpc/tpcc.go | 1 + tpcc/csv.go | 2 +- tpcc/ddl.go | 189 ++++++++++++++++++++++++--------------------- tpcc/ddl_test.go | 18 ++--- tpcc/workload.go | 9 ++- 5 files changed, 115 insertions(+), 104 deletions(-) diff --git a/cmd/go-tpc/tpcc.go b/cmd/go-tpc/tpcc.go index 8573f45..4dd5d80 100644 --- a/cmd/go-tpc/tpcc.go +++ b/cmd/go-tpc/tpcc.go @@ -105,6 +105,7 @@ func registerTpcc(root *cobra.Command) { } cmdPrepare.PersistentFlags().BoolVar(&tpccConfig.NoCheck, "no-check", false, "TPCC prepare check, default false") cmdPrepare.PersistentFlags().BoolVar(&tpccConfig.UseFK, "use-fk", false, "TPCC using foreign key, default false") + cmdPrepare.PersistentFlags().BoolVar(&tpccConfig.UseClusteredIndex, "use-clustered-index", true, "TPCC use clustered index, default true") cmdPrepare.PersistentFlags().StringVar(&tpccConfig.OutputType, "output-type", "", "Output file type."+ " If empty, then load data to db. Current only support csv") cmdPrepare.PersistentFlags().StringVar(&tpccConfig.OutputDir, "output-dir", "", "Output directory for generating file if specified") diff --git a/tpcc/csv.go b/tpcc/csv.go index 5e4e144..30de2c7 100644 --- a/tpcc/csv.go +++ b/tpcc/csv.go @@ -42,7 +42,7 @@ func NewCSVWorkloader(db *sql.DB, cfg *Config) (*CSVWorkLoader, error) { cfg: cfg, initLoadTime: time.Now().Format(timeFormat), tables: make(map[string]bool), - ddlManager: newDDLManager(cfg.Parts, cfg.UseFK, cfg.Warehouses, cfg.PartitionType), + ddlManager: newDDLManager(cfg.Parts, cfg.UseFK, cfg.Warehouses, cfg.PartitionType, cfg.UseClusteredIndex), } var val bool diff --git a/tpcc/ddl.go b/tpcc/ddl.go index c509a9e..550c946 100644 --- a/tpcc/ddl.go +++ b/tpcc/ddl.go @@ -18,14 +18,15 @@ const ( ) type ddlManager struct { - parts int - warehouses int - partitionType int - useFK bool + parts int + warehouses int + partitionType int + useFK bool + useClusteredIndex bool } -func newDDLManager(parts int, useFK bool, warehouses, partitionType int) *ddlManager { - return &ddlManager{parts: parts, useFK: useFK, warehouses: warehouses, partitionType: partitionType} +func newDDLManager(parts int, useFK bool, warehouses, partitionType int, useClusteredIndex bool) *ddlManager { + return &ddlManager{parts: parts, useFK: useFK, warehouses: warehouses, partitionType: partitionType, useClusteredIndex: useClusteredIndex} } func (w *ddlManager) createTableDDL(ctx context.Context, query string, tableName string) error { @@ -123,8 +124,16 @@ func (w *ddlManager) appendPartition(query string, partKeys string) string { // createTables creates tables schema. func (w *ddlManager) createTables(ctx context.Context, driver string) error { if driver == "mysql" { + + var clusteredIndexType string + if w.useClusteredIndex { + clusteredIndexType = "CLUSTERED" + } else { + clusteredIndexType = "NONCLUSTERED" + } + // Warehouse - query := ` + query := fmt.Sprintf(` CREATE TABLE IF NOT EXISTS warehouse ( w_id INT NOT NULL, w_name VARCHAR(10), @@ -135,8 +144,8 @@ CREATE TABLE IF NOT EXISTS warehouse ( w_zip CHAR(9), w_tax DECIMAL(4, 4), w_ytd DECIMAL(12, 2), - PRIMARY KEY (w_id) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY (w_id) /*T![clustered_index] %s */ +)`, clusteredIndexType) query = w.appendPartition(query, "w_id") @@ -145,7 +154,7 @@ CREATE TABLE IF NOT EXISTS warehouse ( } // District - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS district ( d_id INT NOT NULL, d_w_id INT NOT NULL, @@ -158,8 +167,8 @@ CREATE TABLE IF NOT EXISTS district ( d_tax DECIMAL(4, 4), d_ytd DECIMAL(12, 2), d_next_o_id INT, - PRIMARY KEY (d_w_id, d_id) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY (d_w_id, d_id) /*T![clustered_index] %s */ +)`, clusteredIndexType) query = w.appendPartition(query, "d_w_id") @@ -168,32 +177,32 @@ CREATE TABLE IF NOT EXISTS district ( } // Customer - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS customer ( - c_id INT NOT NULL, + c_id INT NOT NULL, c_d_id INT NOT NULL, - c_w_id INT NOT NULL, - c_first VARCHAR(16), - c_middle CHAR(2), - c_last VARCHAR(16), - c_street_1 VARCHAR(20), - c_street_2 VARCHAR(20), - c_city VARCHAR(20), - c_state CHAR(2), - c_zip CHAR(9), - c_phone CHAR(16), - c_since DATETIME, - c_credit CHAR(2), - c_credit_lim DECIMAL(12, 2), - c_discount DECIMAL(4,4), - c_balance DECIMAL(12,2), - c_ytd_payment DECIMAL(12,2), - c_payment_cnt INT, - c_delivery_cnt INT, + c_w_id INT NOT NULL, + c_first VARCHAR(16), + c_middle CHAR(2), + c_last VARCHAR(16), + c_street_1 VARCHAR(20), + c_street_2 VARCHAR(20), + c_city VARCHAR(20), + c_state CHAR(2), + c_zip CHAR(9), + c_phone CHAR(16), + c_since DATETIME, + c_credit CHAR(2), + c_credit_lim DECIMAL(12, 2), + c_discount DECIMAL(4,4), + c_balance DECIMAL(12,2), + c_ytd_payment DECIMAL(12,2), + c_payment_cnt INT, + c_delivery_cnt INT, c_data VARCHAR(500), - PRIMARY KEY(c_w_id, c_d_id, c_id) /*T![clustered_index] CLUSTERED */, + PRIMARY KEY(c_w_id, c_d_id, c_id) /*T![clustered_index] %s */, INDEX idx_customer (c_w_id, c_d_id, c_last, c_first) -)` +)`, clusteredIndexType) query = w.appendPartition(query, "c_w_id") @@ -221,13 +230,13 @@ CREATE TABLE IF NOT EXISTS history ( return err } - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS new_order ( no_o_id INT NOT NULL, no_d_id INT NOT NULL, no_w_id INT NOT NULL, - PRIMARY KEY(no_w_id, no_d_id, no_o_id) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY(no_w_id, no_d_id, no_o_id) /*T![clustered_index] %s */ +)`, clusteredIndexType) query = w.appendPartition(query, "no_w_id") if err := w.createTableDDL(ctx, query, tableNewOrder); err != nil { @@ -235,7 +244,7 @@ CREATE TABLE IF NOT EXISTS new_order ( } // because order is a keyword, so here we use orders instead - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS orders ( o_id INT NOT NULL, o_d_id INT NOT NULL, @@ -245,16 +254,16 @@ CREATE TABLE IF NOT EXISTS orders ( o_carrier_id INT, o_ol_cnt INT, o_all_local INT, - PRIMARY KEY(o_w_id, o_d_id, o_id) /*T![clustered_index] CLUSTERED */, + PRIMARY KEY(o_w_id, o_d_id, o_id) /*T![clustered_index] %s */, INDEX idx_order (o_w_id, o_d_id, o_c_id, o_id) -)` +)`, clusteredIndexType) query = w.appendPartition(query, "o_w_id") if err := w.createTableDDL(ctx, query, tableOrders); err != nil { return err } - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS order_line ( ol_o_id INT NOT NULL, ol_d_id INT NOT NULL, @@ -266,57 +275,57 @@ CREATE TABLE IF NOT EXISTS orders ( ol_quantity INT, ol_amount DECIMAL(6, 2), ol_dist_info CHAR(24), - PRIMARY KEY(ol_w_id, ol_d_id, ol_o_id, ol_number) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY(ol_w_id, ol_d_id, ol_o_id, ol_number) /*T![clustered_index] %s */ +)`, clusteredIndexType) query = w.appendPartition(query, "ol_w_id") if err := w.createTableDDL(ctx, query, tableOrderLine); err != nil { return err } - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS stock ( s_i_id INT NOT NULL, s_w_id INT NOT NULL, s_quantity INT, - s_dist_01 CHAR(24), + s_dist_01 CHAR(24), s_dist_02 CHAR(24), s_dist_03 CHAR(24), - s_dist_04 CHAR(24), - s_dist_05 CHAR(24), - s_dist_06 CHAR(24), - s_dist_07 CHAR(24), - s_dist_08 CHAR(24), - s_dist_09 CHAR(24), - s_dist_10 CHAR(24), - s_ytd INT, - s_order_cnt INT, + s_dist_04 CHAR(24), + s_dist_05 CHAR(24), + s_dist_06 CHAR(24), + s_dist_07 CHAR(24), + s_dist_08 CHAR(24), + s_dist_09 CHAR(24), + s_dist_10 CHAR(24), + s_ytd INT, + s_order_cnt INT, s_remote_cnt INT, s_data VARCHAR(50), - PRIMARY KEY(s_w_id, s_i_id) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY(s_w_id, s_i_id) /*T![clustered_index] %s */ +)`, clusteredIndexType) query = w.appendPartition(query, "s_w_id") if err := w.createTableDDL(ctx, query, tableStock); err != nil { return err } - query = ` + query = fmt.Sprintf(` CREATE TABLE IF NOT EXISTS item ( i_id INT NOT NULL, i_im_id INT, i_name VARCHAR(24), i_price DECIMAL(5, 2), i_data VARCHAR(50), - PRIMARY KEY(i_id) /*T![clustered_index] CLUSTERED */ -)` + PRIMARY KEY(i_id) /*T![clustered_index] %s */ +)`, clusteredIndexType) if err := w.createTableDDL(ctx, query, tableItem); err != nil { return err } if w.useFK { - query = ` + query = ` alter table district add constraint d_warehouse_fkey foreign key (d_w_id) references warehouse (w_id)` @@ -446,26 +455,26 @@ CREATE TABLE IF NOT EXISTS district ( // Customer query = ` CREATE TABLE IF NOT EXISTS customer ( - c_id INT NOT NULL, + c_id INT NOT NULL, c_d_id INT NOT NULL, - c_w_id INT NOT NULL, - c_first VARCHAR(16), - c_middle CHAR(2), - c_last VARCHAR(16), - c_street_1 VARCHAR(20), - c_street_2 VARCHAR(20), - c_city VARCHAR(20), - c_state CHAR(2), - c_zip CHAR(9), - c_phone CHAR(16), - c_since TIMESTAMP, - c_credit CHAR(2), - c_credit_lim DECIMAL(12, 2), - c_discount DECIMAL(4,4), - c_balance DECIMAL(12,2), - c_ytd_payment DECIMAL(12,2), - c_payment_cnt INT, - c_delivery_cnt INT, + c_w_id INT NOT NULL, + c_first VARCHAR(16), + c_middle CHAR(2), + c_last VARCHAR(16), + c_street_1 VARCHAR(20), + c_street_2 VARCHAR(20), + c_city VARCHAR(20), + c_state CHAR(2), + c_zip CHAR(9), + c_phone CHAR(16), + c_since TIMESTAMP, + c_credit CHAR(2), + c_credit_lim DECIMAL(12, 2), + c_discount DECIMAL(4,4), + c_balance DECIMAL(12,2), + c_ytd_payment DECIMAL(12,2), + c_payment_cnt INT, + c_delivery_cnt INT, c_data VARCHAR(500), PRIMARY KEY(c_w_id, c_d_id, c_id) )` @@ -557,18 +566,18 @@ CREATE TABLE IF NOT EXISTS stock ( s_i_id INT NOT NULL, s_w_id INT NOT NULL, s_quantity INT, - s_dist_01 CHAR(24), + s_dist_01 CHAR(24), s_dist_02 CHAR(24), s_dist_03 CHAR(24), - s_dist_04 CHAR(24), - s_dist_05 CHAR(24), - s_dist_06 CHAR(24), - s_dist_07 CHAR(24), - s_dist_08 CHAR(24), - s_dist_09 CHAR(24), - s_dist_10 CHAR(24), - s_ytd INT, - s_order_cnt INT, + s_dist_04 CHAR(24), + s_dist_05 CHAR(24), + s_dist_06 CHAR(24), + s_dist_07 CHAR(24), + s_dist_08 CHAR(24), + s_dist_09 CHAR(24), + s_dist_10 CHAR(24), + s_ytd INT, + s_order_cnt INT, s_remote_cnt INT, s_data VARCHAR(50), PRIMARY KEY(s_w_id, s_i_id) @@ -592,7 +601,7 @@ CREATE TABLE IF NOT EXISTS item ( } if w.useFK { - query = ` + query = ` alter table district add constraint d_warehouse_fkey foreign key (d_w_id) references warehouse (w_id)` diff --git a/tpcc/ddl_test.go b/tpcc/ddl_test.go index 27fdab4..3483852 100644 --- a/tpcc/ddl_test.go +++ b/tpcc/ddl_test.go @@ -3,7 +3,7 @@ package tpcc import "testing" func TestAppendPartition(t *testing.T) { - ddl := newDDLManager(4, false, 4, PartitionTypeHash) + ddl := newDDLManager(4, false, 4, PartitionTypeHash, true) s := ddl.appendPartition("", "Id") expected := `
PARTITION BY HASH(Id) @@ -12,7 +12,7 @@ PARTITIONS 4` t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 4, PartitionTypeRange) + ddl = newDDLManager(4, false, 4, PartitionTypeRange, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY RANGE (Id) @@ -24,7 +24,7 @@ PARTITION BY RANGE (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 23, PartitionTypeRange) + ddl = newDDLManager(4, false, 23, PartitionTypeRange, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY RANGE (Id) @@ -36,7 +36,7 @@ PARTITION BY RANGE (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 12, PartitionTypeListAsHash) + ddl = newDDLManager(4, false, 12, PartitionTypeListAsHash, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) @@ -48,7 +48,7 @@ PARTITION BY LIST (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(3, false, 4, PartitionTypeListAsHash) + ddl = newDDLManager(3, false, 4, PartitionTypeListAsHash, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) @@ -59,7 +59,7 @@ PARTITION BY LIST (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 23, PartitionTypeListAsHash) + ddl = newDDLManager(4, false, 23, PartitionTypeListAsHash, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) @@ -71,7 +71,7 @@ PARTITION BY LIST (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 12, PartitionTypeListAsRange) + ddl = newDDLManager(4, false, 12, PartitionTypeListAsRange, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) @@ -83,7 +83,7 @@ PARTITION BY LIST (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(3, false, 4, PartitionTypeListAsRange) + ddl = newDDLManager(3, false, 4, PartitionTypeListAsRange, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) @@ -94,7 +94,7 @@ PARTITION BY LIST (Id) t.Errorf("got '%s' expected '%s'", s, expected) } - ddl = newDDLManager(4, false, 23, PartitionTypeListAsRange) + ddl = newDDLManager(4, false, 23, PartitionTypeListAsRange, true) s = ddl.appendPartition("
", "Id") expected = `
PARTITION BY LIST (Id) diff --git a/tpcc/workload.go b/tpcc/workload.go index 491ce0f..6c1983f 100644 --- a/tpcc/workload.go +++ b/tpcc/workload.go @@ -77,9 +77,10 @@ type Config struct { MaxMeasureLatency time.Duration // for prepare sub-command only - OutputType string - OutputDir string - SpecifiedTables string + OutputType string + OutputDir string + SpecifiedTables string + UseClusteredIndex bool // connection, retry count when commiting statement fails, default 0 PrepareRetryCount int @@ -146,7 +147,7 @@ func NewWorkloader(db *sql.DB, cfg *Config) (workload.Workloader, error) { db: db, cfg: cfg, initLoadTime: time.Now().Format(timeFormat), - ddlManager: newDDLManager(cfg.Parts, cfg.UseFK, cfg.Warehouses, cfg.PartitionType), + ddlManager: newDDLManager(cfg.Parts, cfg.UseFK, cfg.Warehouses, cfg.PartitionType, cfg.UseClusteredIndex), rtMeasurement: measurement.NewMeasurement(resetMaxLat), waitTimeMeasurement: measurement.NewMeasurement(resetMaxLat), }