PostgreSQL BenchMarksql 性能测试

1 背景知识

本文主要介绍使用 BenchMarksql 6.0PostgreSQL 数据库进行性能测试。

2 BenchMarksql 6.0 配置

su - postgres 
#root>
cd /soft/benchmarksql/target/run
cp sample.postgresql.properties my.properties
vi my.properties

修改以下参数,这只是测试环境所以设置 warehouse=2runMins=1

# General Driver and connection parameters
#
# db={ postgres | oracle | firebird | mariadb | transact-sql }
# driver=<JDBC_DRIVER_CLASS>
# application={ Generic | PostgreSQLStoredProc | OracleStoredProc }
# conn=<JDBC_URI>
# user=<USERNAME>
# password=<PASSWORD>
db=postgres
driver=org.postgresql.Driver
application=Generic
conn=jdbc:postgresql://localhost:5432/testdb
user=benchmarksql
password=benchmarksql

# Scaling and timing configuration
warehouses=10
useWarehouseFrom=-1
useWarehouseTo=-1
loadWorkers=8
monkeys=2
sutThreads=64
maxDeliveryBGThreads=32
maxDeliveryBGPerWarehouse=1
rampupMins=0
rampupSUTMins=5
rampupTerminalMins=5
runMins=5
reportIntervalSecs=10
restartSUTThreadProbability=0.001
keyingTimeMultiplier=0.1
thinkTimeMultiplier=0.1
terminalMultiplier=1
traceTerminalIO=false

# Below are the definitions for the "attempted" transaction mix.
# The TPC-C specification requires minimum percentages for all but
# the NEW_ORDER transaction. If a test run happens to have any of
# those four types fall below those minimums, the entire test is
# invalid. We don't want that to happen, so we specify values just
# a tiny bit above the required minimum.
# The newOrderWeight is calculated as 100.0 - sum(all_other_types).
paymentWeight=43.2
orderStatusWeight=4.2
deliveryWeight=4.2
stockLevelWeight=4.2

# The TPC-C require a minimum of 1% of the NEW_ORDER transactions
# to roll back due to a user entry error (non existing item
# number. Doing it with a strict 1/100th probability can lead to
# undershooting this target, so we default to 1.01% to be sure.
rollbackPercent=1.01

# Directory name to create for collecting detailed result data.
# Comment this out to suppress. Note that the Flask UI will define
# this by itself, so don't specify it if you run through the UI.
resultDirectory=my_result_%tY-%tm-%td_%tH%tM%tS

# BenchmarkSQL includes three OS metric collector scripts implemented
# in Python3. Two require to have collectd installed on the server
# systems, you want to include in the performance report. The data
# will be saved in resultDirectory/data/os-metric.json. The third
# is based on Prometheus and node_exporter.

# mcCollectdMqtt.py is a metric collector that expects the collectd
# instances on the servers to send the metric data to an MQTT broker.

#osCollectorScript=./mcCollectdMqtt.py \
#    -h mymqttbroker.localdomain \
#    -t collectd/mydbserver.localdomain/# \
#    -t collectd/mybackrest.localdomain/#

# mcCollectdGraphite.py is a metric collector that expects the
# collectd instances on the servers to send the metric data to
# a graphite/whisper database and be available through the /render
# API.

#osCollectorScript=./mcCollectdGraphite.py \
#    -u http://mygraphite.localdomain/render/ \
#    -t collectd.mydbserver_localdomain.*.* \
#    -t collectd.mydbserver_localdomain.*.*.* \
#    -t collectd.mybackrest_localdomain.*.* \
#    -t collectd.mybackrest_localdomain.*.*.*

# mcPrometheus.py retrieves the metric data from a Prometheus
# server through the API. It converts the output into the same
# format as the former two produce. The instances listed are
# the same names given in the "instance" label of the metric
# data scraped by Prometheus. The port number will be removed
# in the os-metric.json output.

#osCollectorScript=./mcPrometheus.py \
#    -u http://myprometheus.localdomain:9090/api/v1/query_range \
#    -i mydbserver.localdomain:9100 \
#    -i mybackrest.localdomain:9100

# The report script is what generates the detailed HTML report for
# the benchmark run. It is a Jinja2 template based reporting system
# that includes graphs of various metrics, captured during the benchmark.

reportScript=./generateReport.py -t report_simple.html

#reportScript=./generateReport.py \
#    -t report_extended.html \
#    -c 'mydbserver.localdomain:DB server' \
#    -d 'mydbserver.localdomain:DB server:hda2' \
#    -i 'mydbserver.localdomain:DB server:eth0' \
#    -c 'mybackrest.localdomain:pgbackrest server' \
#    -d 'mybackrest.localdomain:pgbackrest server:hda2' \
#    -i 'mybackrest.localdomain:pgbackrest server:eth0'
Note

对于参数的详细说明,请参考 BenchMarksql 6.0 配置文件 章节。

3 PostgreSQL 配置

psql -U postgres -d testdb
DROP USER benchmarksql;
CREATE USER benchmarksql PASSWORD 'benchmarksql' SUPERUSER;

4 未优化之前的基准测试

4.1 数据生成

su - postgres 
cd /soft/benchmarksql/target/run
./runDatabaseBuild.sh my.properties

以下是数据生成的日志。

# ------------------------------------------------------------
# Loading SQL file ./sql.common/tableCreates.sql
# ------------------------------------------------------------
2024-06-07 14:15:25,263  INFO - create table bmsql_config (
cfg_name    varchar(30) primary key,
cfg_value   varchar(50)
);
2024-06-07 14:15:25,274  INFO - create table bmsql_warehouse (
w_id        integer   not null,
w_ytd       decimal(12,2),
w_tax       decimal(4,4),
w_name      varchar(10),
w_street_1  varchar(20),
w_street_2  varchar(20),
w_city      varchar(20),
w_state     char(2),
w_zip       char(9)
);
2024-06-07 14:15:25,276  INFO - create table bmsql_district (
d_w_id       integer       not null,
d_id         integer       not null,
d_ytd        decimal(12,2),
d_tax        decimal(4,4),
d_next_o_id  integer,
d_name       varchar(10),
d_street_1   varchar(20),
d_street_2   varchar(20),
d_city       varchar(20),
d_state      char(2),
d_zip        char(9)
);
2024-06-07 14:15:25,278  INFO - create table bmsql_customer (
c_w_id         integer        not null,
c_d_id         integer        not null,
c_id           integer        not null,
c_discount     decimal(4,4),
c_credit       char(2),
c_last         varchar(16),
c_first        varchar(16),
c_credit_lim   decimal(12,2),
c_balance      decimal(12,2),
c_ytd_payment  decimal(12,2),
c_payment_cnt  integer,
c_delivery_cnt integer,
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_middle       char(2),
c_data         varchar(500)
);
2024-06-07 14:15:25,281  INFO - create table bmsql_history (
h_c_id   integer,
h_c_d_id integer,
h_c_w_id integer,
h_d_id   integer,
h_w_id   integer,
h_date   timestamp,
h_amount decimal(6,2),
h_data   varchar(24)
);
2024-06-07 14:15:25,283  INFO - create table bmsql_new_order (
no_w_id  integer   not null,
no_d_id  integer   not null,
no_o_id  integer   not null
);
2024-06-07 14:15:25,284  INFO - create table bmsql_oorder (
o_w_id       integer      not null,
o_d_id       integer      not null,
o_id         integer      not null,
o_c_id       integer,
o_carrier_id integer,
o_ol_cnt     integer,
o_all_local  integer,
o_entry_d    timestamp
);
2024-06-07 14:15:25,286  INFO - create table bmsql_order_line (
ol_w_id         integer   not null,
ol_d_id         integer   not null,
ol_o_id         integer   not null,
ol_number       integer   not null,
ol_i_id         integer   not null,
ol_delivery_d   timestamp,
ol_amount       decimal(6,2),
ol_supply_w_id  integer,
ol_quantity     integer,
ol_dist_info    char(24)
);
2024-06-07 14:15:25,287  INFO - create table bmsql_item (
i_id     integer      not null,
i_name   varchar(24),
i_price  decimal(5,2),
i_data   varchar(50),
i_im_id  integer
);
2024-06-07 14:15:25,289  INFO - create table bmsql_stock (
s_w_id       integer       not null,
s_i_id       integer       not null,
s_quantity   integer,
s_ytd        integer,
s_order_cnt  integer,
s_remote_cnt integer,
s_data       varchar(50),
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)
);
# ------------------------------------------------------------
# Loading SQL file ./sql.postgres/extraCommandsBeforeLoad.sql
# ------------------------------------------------------------
2024-06-07 14:15:27,365  INFO - ALTER TABLE bmsql_oorder SET (FILLFACTOR = 85);
2024-06-07 14:15:27,371  INFO - ALTER TABLE bmsql_order_line SET (FILLFACTOR = 85);
2024-06-07 14:15:27,372  INFO - ALTER TABLE bmsql_warehouse SET (FILLFACTOR = 50);
2024-06-07 14:15:27,373  INFO - ALTER TABLE bmsql_district SET (FILLFACTOR = 79);
2024-06-07 14:15:27,374  INFO - ALTER TABLE bmsql_customer SET (FILLFACTOR = 90);
2024-06-07 14:15:27,375  INFO - ALTER TABLE bmsql_stock SET (FILLFACTOR = 95);
# ------------------------------------------------------------
# Loading SQL file ./sql.postgres/storedProcedureCreates.sql
# ------------------------------------------------------------
2024-06-07 14:15:29,274  INFO - CREATE OR REPLACE FUNCTION bmsql_cid_from_clast(
in_c_w_id integer,
in_c_d_id integer,
in_c_last varchar(16))
RETURNS integer AS
$
DECLARE
    cust_cursor CURSOR (
                p_w_id integer, p_d_id integer, p_c_last varchar(16))
        FOR
        SELECT c_id FROM bmsql_customer
            WHERE c_w_id = p_w_id
              AND c_d_id = p_d_id
              AND c_last = p_c_last
            ORDER BY c_first;
    num_cust integer;
    idx_cust integer;
    ret_c_id integer;
BEGIN
    -- Clause 2.5.2.2 Case 2, customer selected based on c_last.
    SELECT INTO num_cust count(*) 
        FROM bmsql_customer
        WHERE c_w_id = in_c_w_id
          AND c_d_id = in_c_d_id
          AND c_last = in_c_last;
    IF num_cust = 0 THEN
        RAISE EXCEPTION 'Customer(s) for C_W_ID=% C_D_ID=% C_LAST=% not found',
                in_c_w_id, in_c_d_id, in_c_last;
    END IF;
    idx_cust = (num_cust + 1) / 2 - 1;

    OPEN cust_cursor(in_c_w_id, in_c_d_id, in_c_last);
    MOVE FORWARD idx_cust IN cust_cursor;
    FETCH FROM cust_cursor INTO ret_c_id;
    CLOSE cust_cursor;

    RETURN ret_c_id;
END;
$
LANGUAGE plpgsql;
2024-06-07 14:15:29,283  INFO - CREATE OR REPLACE FUNCTION bmsql_proc_new_order(
IN in_w_id integer,
IN in_d_id integer,
IN in_c_id integer,
IN in_ol_supply_w_id integer[],
IN in_ol_i_id integer[],
IN in_ol_quantity integer[],
OUT out_w_tax decimal(4, 4),
OUT out_d_tax decimal(4, 4),
OUT out_o_id integer,
OUT out_o_entry_d timestamp,
OUT out_ol_cnt integer,
OUT out_ol_amount decimal(12, 2)[],
OUT out_total_amount decimal(12, 2),
OUT out_c_last varchar(16),
OUT out_c_credit char(2),
OUT out_c_discount decimal(4, 4),
OUT out_i_name varchar(24)[],
OUT out_i_price decimal(5, 2)[],
OUT out_s_quantity integer[],
OUT out_brand_generic char[]
) AS
$
DECLARE
    var_all_local integer := 1;
    var_x integer;
    var_y integer;
    var_tmp integer;
    var_seq integer[15];
    var_item_row record;
    var_stock_row record;
BEGIN
    -- The o_entry_d is now.
    out_o_entry_d := CURRENT_TIMESTAMP;
    out_total_amount := 0.00;

    -- When processing the order lines we must select the STOCK rows
    -- FOR UPDATE. This is because we must perform business logic
    -- (the juggling with the S_QUANTITY) here in the application
    -- and cannot do that in an atomic UPDATE statement while getting
    -- the original value back at the same time (UPDATE ... RETURNING
    -- may not be vendor neutral). This can lead to possible deadlocks
    -- if two transactions try to lock the same two stock rows in
    -- opposite order. To avoid that we process the order lines in
    -- the order of the order of ol_supply_w_id, ol_i_id.
    out_ol_cnt := 0;
    FOR var_x IN 1 .. array_length(in_ol_i_id, 1) LOOP
        IF in_ol_i_id[var_x] IS NOT NULL AND in_ol_i_id[var_x] <> 0 THEN
            out_ol_cnt := out_ol_cnt + 1;
            var_seq[var_x] = var_x;
            IF in_ol_supply_w_id[var_x] <> in_w_id THEN
                var_all_local := 0;
            END IF;
        END IF;
    END LOOP;
    FOR var_x IN 1 .. out_ol_cnt - 1 LOOP
        FOR var_y IN var_x + 1 .. out_ol_cnt LOOP
            IF in_ol_supply_w_id[var_seq[var_y]] < in_ol_supply_w_id[var_seq[var_x]] THEN
                var_tmp = var_seq[var_x];
                var_seq[var_x] = var_seq[var_y];
                var_seq[var_y] = var_tmp;
            ELSE
                IF in_ol_supply_w_id[var_seq[var_y]] = in_ol_supply_w_id[var_seq[var_x]]
                AND in_ol_i_id[var_seq[var_y]] < in_ol_i_id[var_seq[var_x]] THEN
                    var_tmp = var_seq[var_x];
                    var_seq[var_x] = var_seq[var_y];
                    var_seq[var_y] = var_tmp;
                END IF;
            END IF;
        END LOOP;
    END LOOP;

    -- Retrieve the required data from DISTRICT
    SELECT INTO out_d_tax, out_o_id
        d_tax, d_next_o_id
        FROM bmsql_district
        WHERE d_w_id = in_w_id AND d_id = in_d_id
        FOR UPDATE;

    -- Retrieve the required data from CUSTOMER and WAREHOUSE
    SELECT INTO out_w_tax, out_c_last, out_c_credit, out_c_discount
        w_tax, c_last, c_credit, c_discount
        FROM bmsql_customer
        JOIN bmsql_warehouse ON (w_id = c_w_id)
        WHERE c_w_id = in_w_id AND c_d_id = in_d_id AND c_id = in_c_id;

    -- Update the DISTRICT bumping the D_NEXT_O_ID
    UPDATE bmsql_district
        SET d_next_o_id = d_next_o_id + 1
        WHERE d_w_id = in_w_id AND d_id = in_d_id;

    -- Insert the ORDER row
    INSERT INTO bmsql_oorder (
        o_id, o_d_id, o_w_id, o_c_id, o_entry_d,
        o_ol_cnt, o_all_local)
    VALUES (
        out_o_id, in_d_id, in_w_id, in_c_id, out_o_entry_d,
        out_ol_cnt, var_all_local);

    -- Insert the NEW_ORDER row
    INSERT INTO bmsql_new_order (
        no_o_id, no_d_id, no_w_id)
    VALUES (
        out_o_id, in_d_id, in_w_id);

    -- Per ORDER_LINE
    FOR var_x IN 1 .. out_ol_cnt LOOP
        -- We process the lines in the sequence orderd by warehouse, item.
        var_y = var_seq[var_x];
        SELECT INTO var_item_row
                i_name, i_price, i_data
            FROM bmsql_item
            WHERE i_id = in_ol_i_id[var_y];
        IF NOT FOUND THEN
            RAISE EXCEPTION 'Item number is not valid';
        END IF;
        -- Found ITEM
        out_i_name[var_y] = var_item_row.i_name;
        out_i_price[var_y] = var_item_row.i_price;

        SELECT INTO var_stock_row
                s_quantity, s_data,
                s_dist_01, s_dist_02, s_dist_03, s_dist_04, s_dist_05,
                s_dist_06, s_dist_07, s_dist_08, s_dist_09, s_dist_10
            FROM bmsql_stock
            WHERE s_w_id = in_ol_supply_w_id[var_y]
            AND s_i_id = in_ol_i_id[var_y]
            FOR UPDATE;
        IF NOT FOUND THEN
            RAISE EXCEPTION 'STOCK not found: %,%', in_ol_supply_w_id[var_y],
                in_ol_i_id[var_y];
        END IF;

        out_s_quantity[var_y] = var_stock_row.s_quantity;
        out_ol_amount[var_y] = out_i_price[var_y] * in_ol_quantity[var_y];
        IF var_item_row.i_data LIKE '%ORIGINAL%'
        AND var_stock_row.s_data LIKE '%ORIGINAL%' THEN
            out_brand_generic[var_y] := 'B';
        ELSE
            out_brand_generic[var_y] := 'G';
        END IF;
        out_total_amount = out_total_amount +
                out_ol_amount[var_y] * (1.0 - out_c_discount)
                * (1.0 + out_w_tax + out_d_tax);

        -- Update the STOCK row.
        UPDATE bmsql_stock SET
                s_quantity = CASE
                WHEN var_stock_row.s_quantity >= in_ol_quantity[var_y] + 10 THEN
                    var_stock_row.s_quantity - in_ol_quantity[var_y]
                ELSE
                    var_stock_row.s_quantity + 91
                END,
                s_ytd = s_ytd + in_ol_quantity[var_y],
                s_order_cnt = s_order_cnt + 1,
                s_remote_cnt = s_remote_cnt + CASE
                WHEN in_w_id <> in_ol_supply_w_id[var_y] THEN
                    1
                ELSE
                    0
                END
            WHERE s_w_id = in_ol_supply_w_id[var_y]
            AND s_i_id = in_ol_i_id[var_y];

        -- Insert the ORDER_LINE row.
        INSERT INTO bmsql_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 (
            out_o_id, in_d_id, in_w_id, var_y,
            in_ol_i_id[var_y], in_ol_supply_w_id[var_y], in_ol_quantity[var_y],
            out_ol_amount[var_y],
            CASE
                WHEN in_d_id = 1 THEN var_stock_row.s_dist_01
                WHEN in_d_id = 2 THEN var_stock_row.s_dist_02
                WHEN in_d_id = 3 THEN var_stock_row.s_dist_03
                WHEN in_d_id = 4 THEN var_stock_row.s_dist_04
                WHEN in_d_id = 5 THEN var_stock_row.s_dist_05
                WHEN in_d_id = 6 THEN var_stock_row.s_dist_06
                WHEN in_d_id = 7 THEN var_stock_row.s_dist_07
                WHEN in_d_id = 8 THEN var_stock_row.s_dist_08
                WHEN in_d_id = 9 THEN var_stock_row.s_dist_09
                WHEN in_d_id = 10 THEN var_stock_row.s_dist_10
            END);

    END LOOP;

    RETURN;
END;
$
LANGUAGE plpgsql;
2024-06-07 14:15:29,289  INFO - CREATE OR REPLACE FUNCTION bmsql_proc_payment(
IN in_w_id integer,
IN in_d_id integer,
INOUT in_c_id integer,
IN in_c_d_id integer,
IN in_c_w_id integer,
IN in_c_last varchar(16),
IN in_h_amount decimal(6,2),
OUT out_w_name varchar(10),
OUT out_w_street_1 varchar(20),
OUT out_w_street_2 varchar(20),
OUT out_w_city varchar(20),
OUT out_w_state char(2),
OUT out_w_zip char(9),
OUT out_d_name varchar(10),
OUT out_d_street_1 varchar(20),
OUT out_d_street_2 varchar(20),
OUT out_d_city varchar(20),
OUT out_d_state char(2),
OUT out_d_zip char(9),
OUT out_c_first varchar(16),
OUT out_c_middle char(2),
OUT out_c_street_1 varchar(20),
OUT out_c_street_2 varchar(20),
OUT out_c_city varchar(20),
OUT out_c_state char(2),
OUT out_c_zip char(9),
OUT out_c_phone char(16),
OUT out_c_since timestamp,
OUT out_c_credit char(2),
OUT out_c_credit_lim decimal(12,2),
OUT out_c_discount decimal(4,4),
OUT out_c_balance decimal(12,2),
OUT out_c_data varchar(500),
OUT out_h_date timestamp
) AS
$
BEGIN
        out_h_date := CURRENT_TIMESTAMP;

        --Update the DISTRICT
        UPDATE bmsql_district
                SET d_ytd = d_ytd + in_h_amount
                WHERE d_w_id = in_w_id AND d_id = in_d_id;

        --Select the DISTRICT
        SELECT INTO out_d_name, out_d_street_1, out_d_street_2, 
                    out_d_city, out_d_state, out_d_zip
                d_name, d_street_1, d_street_2, d_city, d_state, d_zip
            FROM bmsql_district
            WHERE d_w_id = in_w_id AND d_id = in_d_id
            FOR UPDATE;

        --Update the WAREHOUSE
        UPDATE bmsql_warehouse
            SET w_ytd = w_ytd + in_h_amount
            WHERE w_id = in_w_id;

        --Select the WAREHOUSE
        SELECT INTO out_w_name, out_w_street_1, out_w_street_2,
                    out_w_city, out_w_state, out_w_zip
                w_name, w_street_1, w_street_2, w_city, w_state, w_zip
            FROM bmsql_warehouse
            WHERE w_id = in_w_id
            FOR UPDATE;

        --If C_Last is given instead of C_ID (60%), determine the C_ID.
        IF in_c_last IS NOT NULL THEN
            in_c_id = bmsql_cid_from_clast(in_c_w_id, in_c_d_id, in_c_last);
        END IF;

        --Select the CUSTOMER
        SELECT INTO out_c_first, out_c_middle, in_c_last, out_c_street_1,
                    out_c_street_2, out_c_city, out_c_state, out_c_zip,
                    out_c_phone, out_c_since, out_c_credit, out_c_credit_lim,
                    out_c_discount, out_c_balance
                c_first, c_middle, c_last, c_street_1,
                c_street_2, c_city, c_state, c_zip,
                c_phone, c_since, c_credit, c_credit_lim,
                c_discount, c_balance
            FROM bmsql_customer
            WHERE c_w_id = in_c_w_id AND c_d_id = in_c_d_id AND c_id = in_c_id
            FOR UPDATE;

        --Update the CUSTOMER
        out_c_balance = out_c_balance-in_h_amount;
        IF out_c_credit = 'GC' THEN
            --Customer with good credit, don't update C_DATA
            UPDATE bmsql_customer
                SET c_balance = c_balance - in_h_amount,
                    c_ytd_payment = c_ytd_payment + in_h_amount,
                    c_payment_cnt = c_payment_cnt + 1
                WHERE c_w_id = in_c_w_id AND c_d_id=in_c_d_id AND c_id=in_c_id;
            out_c_data := '';
        ELSE
        --Customer with bad credit, need to do the C_DATA work.
            SELECT INTO out_c_data
                    c_data
                FROM bmsql_customer
                WHERE c_w_id = in_c_w_id AND c_d_id = in_c_d_id
                  AND c_id = in_c_id;
            out_c_data := substring('C_ID=' || in_c_id::text ||
                                    ' C_D_ID=' || in_c_d_id::text ||
                                    ' C_W_ID=' || in_c_w_id::text ||
                                    ' D_ID=' || in_d_id::text ||
                                    ' W_ID=' || in_w_id::text ||
                                    ' H_AMOUNT=' || round(in_h_amount,2)::text || '   ' ||
                                    out_c_data from 1 for 500);

            UPDATE bmsql_customer
                SET c_balance = c_balance - in_h_amount,
                    c_ytd_payment = c_ytd_payment + in_h_amount,
                    c_payment_cnt = c_payment_cnt + 1,
                    c_data = out_c_data
                WHERE c_w_id = in_c_w_id AND c_d_id = in_c_d_id
                  AND c_id = in_c_id;
        END IF;

        --Insert the HISTORY row
        INSERT INTO bmsql_history (
                    h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id,
                    h_date, h_amount, h_data)
        VALUES (
                    in_c_id, in_c_d_id, in_c_w_id, in_d_id, in_w_id,
                    out_h_date, in_h_amount, out_w_name||'    '|| out_d_name
        );
END;
$
LANGUAGE plpgsql;
2024-06-07 14:15:29,292  INFO - CREATE OR REPLACE FUNCTION bmsql_proc_order_status(
IN in_w_id integer,
IN in_d_id integer,
INOUT in_c_id integer,
IN in_c_last varchar(16),
OUT out_c_first varchar(16),
OUT out_c_middle char(2),
OUT out_c_balance decimal(12,2),
OUT out_o_id integer,
OUT out_o_entry_d varchar(24),
OUT out_o_carrier_id integer,
OUT out_ol_supply_w_id integer[],
OUT out_ol_i_id integer[],
OUT out_ol_quantity integer[],
OUT out_ol_amount decimal(12,2)[],
OUT out_ol_delivery_d timestamp[]
) AS
$
DECLARE
        v_order_line    record;
        v_ol_idx                integer := 1;
BEGIN
    --If C_LAST is given instead of C_ID (60%), determine the C_ID.
    IF in_c_last IS NOT NULL THEN
                in_c_id = bmsql_cid_from_clast(in_w_id, in_d_id, in_c_last);
    END IF;

    --Select the CUSTOMER
    SELECT INTO out_c_first, out_c_middle, in_c_last, out_c_balance
                        c_first, c_middle, c_last, c_balance
                FROM bmsql_customer
                WHERE c_w_id=in_w_id AND c_d_id=in_d_id AND c_id = in_c_id;

    --Select the last ORDER for this customer.
    SELECT INTO out_o_id, out_o_entry_d, out_o_carrier_id
                        o_id, o_entry_d, coalesce(o_carrier_id, -1)
                FROM bmsql_oorder
                WHERE o_w_id = in_w_id AND o_d_id = in_d_id AND o_c_id = in_c_id
                AND o_id = (
                        SELECT max(o_id)
                                FROM bmsql_oorder
                                WHERE o_w_id = in_w_id AND o_d_id = in_d_id AND o_c_id = in_c_id
                        );

        FOR v_order_line IN SELECT ol_i_id, ol_supply_w_id, ol_quantity,
                                ol_amount, ol_delivery_d
                        FROM bmsql_order_line
                        WHERE ol_w_id = in_w_id AND ol_d_id = in_d_id AND ol_o_id = out_o_id
                        ORDER BY ol_w_id, ol_d_id, ol_o_id, ol_number
                        LOOP
            out_ol_i_id[v_ol_idx] = v_order_line.ol_i_id;
            out_ol_supply_w_id[v_ol_idx] = v_order_line.ol_supply_w_id;
            out_ol_quantity[v_ol_idx] = v_order_line.ol_quantity;
            out_ol_amount[v_ol_idx] = v_order_line.ol_amount;
            out_ol_delivery_d[v_ol_idx] = v_order_line.ol_delivery_d;
                v_ol_idx = v_ol_idx + 1;
        END LOOP;

    WHILE v_ol_idx < 16 LOOP
                out_ol_i_id[v_ol_idx] = 0;
                out_ol_supply_w_id[v_ol_idx] = 0;
                out_ol_quantity[v_ol_idx] = 0;
                out_ol_amount[v_ol_idx] = 0.0;
                out_ol_delivery_d[v_ol_idx] = NULL;
                v_ol_idx = v_ol_idx +1;
    END LOOP;
END;
$
Language plpgsql;
2024-06-07 14:15:29,295  INFO - CREATE OR REPLACE FUNCTION bmsql_proc_stock_level(
IN in_w_id integer,
IN in_d_id integer,
IN in_threshold integer,
OUT out_low_stock integer
) AS
$
BEGIN
    SELECT INTO out_low_stock
                        count(*) AS low_stock
                FROM (
                        SELECT s_w_id, s_i_id, s_quantity
                        FROM bmsql_stock
                        WHERE s_w_id = in_w_id AND s_quantity < in_threshold
                          AND s_i_id IN (
                                SELECT ol_i_id
                                        FROM bmsql_district
                                        JOIN bmsql_order_line ON ol_w_id = d_w_id
                                         AND ol_d_id = d_id
                                         AND ol_o_id >= d_next_o_id - 20
                                         AND ol_o_id < d_next_o_id
                                        WHERE d_w_id = in_w_id AND d_id = in_d_id
                                )
                        ) AS L;
END;
$
LANGUAGE plpgsql;
2024-06-07 14:15:29,296  INFO - CREATE OR REPLACE FUNCTION bmsql_proc_delivery_bg(
IN in_w_id integer,
IN in_o_carrier_id integer,
IN in_ol_delivery_d timestamp,
OUT out_delivered_o_id integer[]
) AS
$
DECLARE
        var_d_id integer;
        var_o_id integer;
        var_c_id integer;
        var_sum_ol_amount decimal(12, 2);
BEGIN
        FOR var_d_id IN 1..10 LOOP
                var_o_id = -1;
                /*
                 * Try to find the oldest undelivered order for this
                 * DISTRICT. There may not be one, which is a case
                 * that needs to be reported.
                */
                WHILE var_o_id < 0 LOOP
                        SELECT INTO var_o_id
                                        no_o_id
                                FROM bmsql_new_order
                        WHERE no_w_id = in_w_id AND no_d_id = var_d_id
                        ORDER BY no_o_id ASC;
                        IF NOT FOUND THEN
                            var_o_id = -1;
                                EXIT;
                        END IF;

                        DELETE FROM bmsql_new_order
                                WHERE no_w_id = in_w_id AND no_d_id = var_d_id
                                  AND no_o_id = var_o_id;
                        IF NOT FOUND THEN
                            var_o_id = -1;
                        END IF;
                END LOOP;

                IF var_o_id < 0 THEN
                        -- No undelivered NEW_ORDER found for this District.
                        var_d_id = var_d_id + 1;
                        CONTINUE;
                END IF;

                /*
                 * We found out oldert undelivered order for this DISTRICT
                 * and the NEW_ORDER line has been deleted. Process the
                 * rest of the DELIVERY_BG.
                */

                -- Update the ORDER setting the o_carrier_id.
                UPDATE bmsql_oorder
                        SET o_carrier_id = in_o_carrier_id
                        WHERE o_w_id = in_w_id AND o_d_id = var_d_id AND o_id = var_o_id;

                -- Get the o_c_id from the ORDER.
                SELECT INTO var_c_id
                                o_c_id
                        FROM bmsql_oorder
                        WHERE o_w_id = in_w_id AND o_d_id = var_d_id AND o_id = var_o_id;

                -- Update ORDER_LINE setting the ol_delivery_d.
                UPDATE bmsql_order_line
                        SET ol_delivery_d = in_ol_delivery_d
                        WHERE ol_w_id = in_w_id AND ol_d_id = var_d_id
                          AND ol_o_id = var_o_id;

                -- SELECT the sum(ol_amount) from ORDER_LINE.
                SELECT INTO var_sum_ol_amount
                                sum(ol_amount) AS sum_ol_amount
                        FROM bmsql_order_line
                        WHERE ol_w_id = in_w_id AND ol_d_id = var_d_id
                          AND ol_o_id = var_o_id;

                -- Update the CUSTOMER.
                UPDATE bmsql_customer
                        SET c_balance = c_balance + var_sum_ol_amount,
                                c_delivery_cnt = c_delivery_cnt + 1
                        WHERE c_w_id = in_w_id AND c_d_id = var_d_id and c_id = var_c_id;

                out_delivered_o_id[var_d_id] = var_o_id;

                var_d_id = var_d_id +1 ;
        END LOOP;
END;
$
LANGUAGE plpgsql;
2024-06-07 14:15:30,926  INFO - Starting BenchmarkSQL LoadData
2024-06-07 14:15:30,930  INFO - 
2024-06-07 14:15:30,932  INFO - random initialized
2024-06-07 14:15:30,934  INFO - driver=org.postgresql.Driver
2024-06-07 14:15:30,939  INFO - conn=jdbc:postgresql://localhost:5432/testdb
2024-06-07 14:15:30,939  INFO - user=benchmarksql
2024-06-07 14:15:30,939  INFO - password=***********
2024-06-07 14:15:30,939  INFO - warehouses=10
2024-06-07 14:15:30,939  INFO - loadWorkers=8
2024-06-07 14:15:30,940  WARN - fileLocation (not defined)
2024-06-07 14:15:30,940  WARN - csvNullValue (not defined - using default 'NULL')
2024-06-07 14:15:30,940  INFO - 
2024-06-07 14:15:31,382  INFO - Worker 000: Loading ITEM
2024-06-07 14:15:31,445  INFO - Worker 001: Loading Warehouse      1
2024-06-07 14:15:31,505  INFO - Worker 002: Loading Warehouse      2
2024-06-07 14:15:31,604  INFO - Worker 003: Loading Warehouse      3
2024-06-07 14:15:31,725  INFO - Worker 004: Loading Warehouse      4
2024-06-07 14:15:32,029  INFO - Worker 005: Loading Warehouse      5
2024-06-07 14:15:32,177  INFO - Worker 006: Loading Warehouse      6
2024-06-07 14:15:32,268  INFO - Worker 007: Loading Warehouse      7
2024-06-07 14:15:40,030  INFO - Worker 000: Loading ITEM done
2024-06-07 14:15:40,030  INFO - Worker 000: Loading Warehouse      8
2024-06-07 14:15:52,431  INFO - Worker 001: Loading Warehouse      1 done
2024-06-07 14:15:52,431  INFO - Worker 001: Loading Warehouse      9
2024-06-07 14:15:53,044  INFO - Worker 002: Loading Warehouse      2 done
2024-06-07 14:15:53,044  INFO - Worker 002: Loading Warehouse     10
2024-06-07 14:15:53,399  INFO - Worker 003: Loading Warehouse      3 done
2024-06-07 14:15:53,400  INFO - Loading Orders with O_ID    1 and higher
2024-06-07 14:15:53,533  INFO - Worker 005: Loading Warehouse      5 done
2024-06-07 14:15:53,719  INFO - Worker 006: Loading Warehouse      6 done
2024-06-07 14:15:53,788  INFO - Worker 004: Loading Warehouse      4 done
2024-06-07 14:15:54,199  INFO - Worker 007: Loading Warehouse      7 done
2024-06-07 14:15:58,306  INFO - Worker 000: Loading Warehouse      8 done
2024-06-07 14:15:58,879  INFO - Loading Orders with O_ID  101 and higher
2024-06-07 14:16:03,146  INFO - Loading Orders with O_ID  201 and higher
2024-06-07 14:16:05,059  INFO - Worker 001: Loading Warehouse      9 done
2024-06-07 14:16:05,572  INFO - Worker 002: Loading Warehouse     10 done
2024-06-07 14:16:06,372  INFO - Loading Orders with O_ID  301 and higher
2024-06-07 14:16:08,973  INFO - Loading Orders with O_ID  401 and higher
2024-06-07 14:16:11,155  INFO - Loading Orders with O_ID  501 and higher
2024-06-07 14:16:13,563  INFO - Loading Orders with O_ID  601 and higher
2024-06-07 14:16:16,076  INFO - Loading Orders with O_ID  701 and higher
2024-06-07 14:16:18,437  INFO - Loading Orders with O_ID  801 and higher
2024-06-07 14:16:20,805  INFO - Loading Orders with O_ID  901 and higher
2024-06-07 14:16:23,291  INFO - Loading Orders with O_ID 1001 and higher
2024-06-07 14:16:25,600  INFO - Loading Orders with O_ID 1101 and higher
2024-06-07 14:16:28,181  INFO - Loading Orders with O_ID 1201 and higher
2024-06-07 14:16:30,557  INFO - Loading Orders with O_ID 1301 and higher
2024-06-07 14:16:32,825  INFO - Loading Orders with O_ID 1401 and higher
2024-06-07 14:16:35,334  INFO - Loading Orders with O_ID 1501 and higher
2024-06-07 14:16:37,764  INFO - Loading Orders with O_ID 1601 and higher
2024-06-07 14:16:40,427  INFO - Loading Orders with O_ID 1701 and higher
2024-06-07 14:16:43,240  INFO - Loading Orders with O_ID 1801 and higher
2024-06-07 14:16:45,620  INFO - Loading Orders with O_ID 1901 and higher
2024-06-07 14:16:48,635  INFO - Loading Orders with O_ID 2001 and higher
2024-06-07 14:16:51,566  INFO - Loading Orders with O_ID 2101 and higher
2024-06-07 14:16:54,364  INFO - Loading Orders with O_ID 2201 and higher
2024-06-07 14:16:56,988  INFO - Loading Orders with O_ID 2301 and higher
2024-06-07 14:17:00,048  INFO - Loading Orders with O_ID 2401 and higher
2024-06-07 14:17:03,447  INFO - Loading Orders with O_ID 2501 and higher
2024-06-07 14:17:06,361  INFO - Loading Orders with O_ID 2601 and higher
2024-06-07 14:17:09,531  INFO - Loading Orders with O_ID 2701 and higher
2024-06-07 14:17:12,844  INFO - Loading Orders with O_ID 2801 and higher
2024-06-07 14:17:15,430  INFO - Loading Orders with O_ID 2901 and higher
2024-06-07 14:17:17,736  INFO - Loading Orders done
# ------------------------------------------------------------
# Loading SQL file ./sql.common/indexCreates.sql
# ------------------------------------------------------------
2024-06-07 14:17:19,579  INFO - alter table bmsql_warehouse add constraint bmsql_warehouse_pkey
primary key (w_id);
2024-06-07 14:17:19,594  INFO - alter table bmsql_district add constraint bmsql_district_pkey
primary key (d_w_id, d_id);
2024-06-07 14:17:19,597  INFO - alter table bmsql_customer add constraint bmsql_customer_pkey
primary key (c_w_id, c_d_id, c_id);
2024-06-07 14:17:19,882  INFO - create index bmsql_customer_idx1
on  bmsql_customer (c_w_id, c_d_id, c_last, c_first);
2024-06-07 14:17:20,634  INFO - alter table bmsql_oorder add constraint bmsql_oorder_pkey
primary key (o_w_id, o_d_id, o_id);
2024-06-07 14:17:20,890  INFO - create unique index bmsql_oorder_idx1
on  bmsql_oorder (o_w_id, o_d_id, o_carrier_id, o_id);
2024-06-07 14:17:21,192  INFO - alter table bmsql_new_order add constraint bmsql_new_order_pkey
primary key (no_w_id, no_d_id, no_o_id);
2024-06-07 14:17:21,298  INFO - alter table bmsql_order_line add constraint bmsql_order_line_pkey
primary key (ol_w_id, ol_d_id, ol_o_id, ol_number);
2024-06-07 14:17:24,281  INFO - alter table bmsql_stock add constraint bmsql_stock_pkey
primary key (s_w_id, s_i_id);
2024-06-07 14:17:25,823  INFO - alter table bmsql_item add constraint bmsql_item_pkey
primary key (i_id);
# ------------------------------------------------------------
# Loading SQL file ./sql.common/foreignKeys.sql
# ------------------------------------------------------------
2024-06-07 14:17:27,558  INFO - alter table bmsql_district add constraint d_warehouse_fkey
foreign key (d_w_id)
references bmsql_warehouse (w_id);
2024-06-07 14:17:27,568  INFO - alter table bmsql_customer add constraint c_district_fkey
foreign key (c_w_id, c_d_id)
references bmsql_district (d_w_id, d_id);
2024-06-07 14:17:27,630  INFO - alter table bmsql_history add constraint h_customer_fkey
foreign key (h_c_w_id, h_c_d_id, h_c_id)
references bmsql_customer (c_w_id, c_d_id, c_id);
2024-06-07 14:17:27,972  INFO - alter table bmsql_history add constraint h_district_fkey
foreign key (h_w_id, h_d_id)
references bmsql_district (d_w_id, d_id);
2024-06-07 14:17:28,038  INFO - alter table bmsql_new_order add constraint no_order_fkey
foreign key (no_w_id, no_d_id, no_o_id)
references bmsql_oorder (o_w_id, o_d_id, o_id);
2024-06-07 14:17:28,208  INFO - alter table bmsql_oorder add constraint o_customer_fkey
foreign key (o_w_id, o_d_id, o_c_id)
references bmsql_customer (c_w_id, c_d_id, c_id);
2024-06-07 14:17:28,593  INFO - alter table bmsql_order_line add constraint ol_order_fkey
foreign key (ol_w_id, ol_d_id, ol_o_id)
references bmsql_oorder (o_w_id, o_d_id, o_id);
2024-06-07 14:17:29,790  INFO - alter table bmsql_order_line add constraint ol_stock_fkey
foreign key (ol_supply_w_id, ol_i_id)
references bmsql_stock (s_w_id, s_i_id);
2024-06-07 14:17:31,501  INFO - alter table bmsql_stock add constraint s_warehouse_fkey
foreign key (s_w_id)
references bmsql_warehouse (w_id);
2024-06-07 14:17:31,659  INFO - alter table bmsql_stock add constraint s_item_fkey
foreign key (s_i_id)
references bmsql_item (i_id);
# ------------------------------------------------------------
# Loading SQL file ./sql.postgres/buildFinish.sql
# ------------------------------------------------------------
2024-06-07 14:17:33,580  INFO - -- ----
2024-06-07 14:17:33,584  INFO - -- Extra commands to run after the tables are created, loaded,
2024-06-07 14:17:33,584  INFO - -- indexes built and extra's created.
2024-06-07 14:17:33,584  INFO - -- PostgreSQL version.
2024-06-07 14:17:33,585  INFO - -- ----
2024-06-07 14:17:33,587  INFO - vacuum freeze analyze;
[postgres@node1 run]$ 

4.2 进行基准测试

可以通过两种方式进行基准测试。

  1. 第一种方式:使用命令行进行基准测试。
nohup ./runBenchmark.sh my.properties  > run.log 2>&1 &
  1. 第二种方式:使用 BenchmarkSQL WEB服务 可以运行基准测试,并直观的看到性能的结果。

4.3 基准测试报告解读

使用 BenchmarkSQL WEB服务 可以运行基准测试,并直观的看到性能的结果。
1、请点击 [[BenchmarkSQL Run.html]]报告并查看基准测试的结果。
2、这里是部分截图。
BenchmarkSQL_Run_1.png|700
BenchmarkSQL_Run_2.png|700
BenchmarkSQL_Run_3.png|700
BenchmarkSQL_Run_4png|700

5 已优化之后的基准测试

#todo

6 小结 & FAQ

6.1 重建测试数据

  1. 切换用户进入 run 目录。
su - postgres 
#postgres>
cd /soft/benchmarksql/target/run

  1. 清除数据。
./runDatabaseDestroy.sh my.properties

  1. 重建数据。
./runDatabaseBuild.sh my.properties