From 3a92e0a9ff99f5d68bdec43544955aaf1c09a2fe Mon Sep 17 00:00:00 2001 From: Nathan VanBenschoten Date: Thu, 15 Feb 2018 17:44:37 -0500 Subject: [PATCH] DNM use RETURNING NOTHING to parallelize statements --- tpcc/delivery.go | 52 ++++++++++++++++++++++++++++------------------- tpcc/new_order.go | 18 +++++++++------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/tpcc/delivery.go b/tpcc/delivery.go index 39c370d..e46de68 100644 --- a/tpcc/delivery.go +++ b/tpcc/delivery.go @@ -62,9 +62,9 @@ func (del delivery) run(db *sql.DB, wID int) (interface{}, error) { if err != nil { return err } - delNewOrder, err := tx.Prepare(` - DELETE FROM new_order - WHERE no_w_id = $1 AND no_d_id = $2 AND no_o_id = $3`) + sumOrderLine, err := tx.Prepare(` + SELECT SUM(ol_amount) FROM order_line + WHERE ol_w_id = $1 AND ol_d_id = $2 AND ol_o_id = $3`) if err != nil { return err } @@ -76,16 +76,18 @@ func (del delivery) run(db *sql.DB, wID int) (interface{}, error) { if err != nil { return err } - updateOrderLine, err := tx.Prepare(` - UPDATE order_line - SET ol_delivery_d = $1 - WHERE ol_w_id = $2 AND ol_d_id = $3 AND ol_o_id = $4`) + delNewOrder, err := tx.Prepare(` + DELETE FROM new_order + WHERE no_w_id = $1 AND no_d_id = $2 AND no_o_id = $3 + RETURNING NOTHING`) if err != nil { return err } - sumOrderLine, err := tx.Prepare(` - SELECT SUM(ol_amount) FROM order_line - WHERE ol_w_id = $1 AND ol_d_id = $2 AND ol_o_id = $3`) + updateOrderLine, err := tx.Prepare(` + UPDATE order_line + SET ol_delivery_d = $1 + WHERE ol_w_id = $2 AND ol_d_id = $3 AND ol_o_id = $4 + RETURNING NOTHING`) if err != nil { return err } @@ -93,36 +95,44 @@ func (del delivery) run(db *sql.DB, wID int) (interface{}, error) { UPDATE customer SET (c_balance, c_delivery_cnt) = (c_Balance + $1, c_delivery_cnt + 1) - WHERE c_w_id = $2 AND c_d_id = $3 AND c_id = $4`) + WHERE c_w_id = $2 AND c_d_id = $3 AND c_id = $4 + RETURNING NOTHING`) if err != nil { return err } // 2.7.4.2. For each district: - for dID := 1; dID <= 10; dID++ { - var oID int - if err := getNewOrder.QueryRow(wID, dID).Scan(&oID); err != nil { + const ids = 10 + var oIDs [ids]int + var olTotals [ids]float64 + var oCIDs [ids]int + for dID := 1; dID <= ids; dID++ { + if err := getNewOrder.QueryRow(wID, dID).Scan(&oIDs[dID-1]); err != nil { // If no matching order is found, the delivery of this order is skipped. if err != sql.ErrNoRows { return err } continue } - if _, err := delNewOrder.Exec(wID, dID, oID); err != nil { + oID := &oIDs[dID-1] + if err := sumOrderLine.QueryRow(wID, dID, oID).Scan(&olTotals[dID-1]); err != nil { return err } - var oCID int - if err := updateOrder.QueryRow(oCarrierID, wID, dID, oID).Scan(&oCID); err != nil { + if err := updateOrder.QueryRow(oCarrierID, wID, dID, oID).Scan(&oCIDs[dID-1]); err != nil { return err } - if _, err := updateOrderLine.Exec(olDeliveryD, wID, dID, oID); err != nil { + } + for dID := 1; dID <= ids; dID++ { + oID := oIDs[dID-1] + olTotal := olTotals[dID-1] + oCID := oCIDs[dID-1] + if _, err := delNewOrder.Exec(wID, dID, oID); err != nil { return err } - var olTotal float64 - if err := sumOrderLine.QueryRow(wID, dID, oID).Scan(&olTotal); err != nil { + if _, err := updateOrderLine.Exec(olDeliveryD, wID, dID, oID); err != nil { return err } - if _, err := updateCustomer.Exec(olTotal, wID, dID, oID); err != nil { + if _, err := updateCustomer.Exec(olTotal, wID, dID, oCID); err != nil { return err } } diff --git a/tpcc/new_order.go b/tpcc/new_order.go index 5edd617..56a9bb0 100644 --- a/tpcc/new_order.go +++ b/tpcc/new_order.go @@ -49,6 +49,7 @@ type orderItem struct { iPrice float64 // item price olAmount float64 // order amount olDeliveryD pq.NullTime + distInfo string // contents of s_dist_xx remoteWarehouse bool // internal use - item from a local or remote warehouse? } @@ -158,13 +159,13 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { // Insert row into the orders and new orders table. if _, err := tx.Exec(` INSERT INTO "order" (o_id, o_d_id, o_w_id, o_c_id, o_entry_d, o_ol_cnt, o_all_local) - VALUES ($1, $2, $3, $4, $5, $6, $7)`, + VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING NOTHING`, d.oID, d.dID, d.wID, d.cID, d.oEntryD, d.oOlCnt, allLocal); err != nil { return err } if _, err := tx.Exec(` INSERT INTO new_order (no_o_id, no_d_id, no_w_id) - VALUES ($1, $2, $3)`, + VALUES ($1, $2, $3) RETURNING NOTHING`, d.oID, d.dID, d.wID); err != nil { return err } @@ -187,7 +188,7 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { } insertOrderLine, err := tx.Prepare(` INSERT INTO order_line(ol_o_id, ol_d_id, ol_w_id, ol_number, ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_dist_info) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING NOTHING`) if err != nil { return err } @@ -196,7 +197,8 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { // 2.4.2.2: For each o_ol_cnt item in the order, query the relevant item // row, update the stock row to account for the order, and insert a new // line into the order_line table to reflect the item on the order. - for i, item := range d.items { + for i := range d.items { + item := &d.items[i] if err := selectItem.QueryRow(item.olIID).Scan(&item.iPrice, &item.iName, &iData); err != nil { if rollback && item.olIID < 0 { // 2.4.2.3: roll back when we're expecting a rollback due to @@ -209,10 +211,10 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { return err } - var distInfo, sData string + var sData string if err := updateStock.QueryRow( item.olQuantity, item.remoteWarehouse, item.olIID, item.olSupplyWID, - ).Scan(&distInfo, &sData); err != nil { + ).Scan(&item.distInfo, &sData); err != nil { return err } if strings.Contains(sData, originalString) && strings.Contains(iData, originalString) { @@ -223,6 +225,8 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { item.olAmount = float64(item.olQuantity) * item.iPrice d.totalAmount += item.olAmount + } + for i, item := range d.items { if _, err := insertOrderLine.Exec( d.oID, // ol_o_id d.dID, @@ -232,7 +236,7 @@ func (n newOrder) run(db *sql.DB, wID int) (interface{}, error) { item.olSupplyWID, item.olQuantity, item.olAmount, - distInfo, // ol_dist_info is set to the contents of s_dist_xx + item.distInfo, // ol_dist_info is set to the contents of s_dist_xx ); err != nil { return err }