Stock load

Simulates a warehouse of an online store: creates multi-product orders, gets a list of orders per customer.

Types of load

This load test runs 5 types of load:

  • getCustomerHistory reads the specified number of orders for the customer with id = 10000. This creates a workload to read the same rows from different threads.
  • getRandomCustomerHistory reads the specified number of orders made by a randomly selected customer. A load that reads data from different threads is created.
  • insertRandomOrder creates a random order. For example, a customer has created an order of 2 products, but hasn’t yet paid for it, hence the quantities in stock aren’t decreased for the products. The database writes the data about the order and products. The read/write load is created (the INSERT checks for an existing entry before inserting the data).
  • submitRandomOrder creates and processes a randomly generated order. For example, a customer has created and paid an order of 2 products. The data about the order and products is written to the database, product availability is checked and quantities in stock are decreased. A mixed data load is created.
  • submitSameOrder: Creates orders with the same set of products. For example, all customers buy the same set of products (a newly released phone and a charger). This creates a workload of competing updates of the same rows in the table.

Load test initialization

To get started, create tables and populate them with data:

  1. ydb workload stock init [init options...]

Stock load - 图1

See the description of the command to run the data load:

  1. ydb workload init --help

Stock load - 图2

Available parameters

Parameter nameShort nameParameter description
—products <value>-p <value>Number of products. Valid values: between 1 and 500000. The default value is 100.
—quantity <value>-q <value>Quantity of each product in stock. Default value: 1000.
—orders <value>-o <value>Initial number of orders in the database. The default value is 100.
—min-partitions <value>-Minimum number of shards for tables. Default value: 40.
—auto-partition <value>-Enabling/disabling auto-sharding. Possible values: 0 or 1. Default: 1.

3 tables are created using the following DDL statements:

  1. CREATE TABLE `stock`(product Utf8, quantity Int64, PRIMARY KEY(product)) WITH (AUTO_PARTITIONING_BY_LOAD = ENABLED, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = <min-partitions>);
  2. CREATE TABLE `orders`(id Uint64, customer Utf8, created Datetime, processed Datetime, PRIMARY KEY(id), INDEX ix_cust GLOBAL ON (customer, created)) WITH (READ_REPLICAS_SETTINGS = "per_az:1", AUTO_PARTITIONING_BY_LOAD = ENABLED, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = <min-partitions>, UNIFORM_PARTITIONS = <min-partitions>, AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = 1000);
  3. CREATE TABLE `orderLines`(id_order Uint64, product Utf8, quantity Int64, PRIMARY KEY(id_order, product)) WITH (AUTO_PARTITIONING_BY_LOAD = ENABLED, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = <min-partitions>, UNIFORM_PARTITIONS = <min-partitions>, AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = 1000);

Stock load - 图3

Load initialization examples

Creating a database with 1000 products, 10000 items of each product, and no orders:

  1. ydb workload stock init -p 1000 -q 10000 -o 0

Stock load - 图4

Creating a database with 10 products, 100 items of each product, 10 orders, and a minimum number of shards equal 100:

  1. ydb workload stock init -p 10 -q 100 -o 10 ----min-partitions 100

Stock load - 图5

Running a load test

To run the load, execute the command:

  1. ydb workload stock run [workload type...] [global workload options...] [specific workload options...]

Stock load - 图6

During this test, workload statistics for each time window are displayed on the screen.

See the description of the command to run the data load:

  1. ydb workload run --help

Stock load - 图7

Global parameters for all types of load

Parameter nameShort nameParameter description
—seconds <value>-s <value>Duration of the test, in seconds. Default value: 10.
—threads <value>-t <value>The number of parallel threads creating the load. Default value: 10.
—quiet-Outputs only the final test result.
—print-timestamp-Print the time together with the statistics of each time window.
—client-timeout-Transport timeout in milliseconds.
—operation-timeout-Operation timeout in milliseconds.
—cancel-after-Timeout for canceling an operation in milliseconds.
—window-Statistics collection window in seconds. Default: 1.

getCustomerHistory load

This type of load reads the specified number of orders for the customer with id = 10000.

YQL query:

  1. DECLARE $cust AS Utf8;
  2. DECLARE $limit AS UInt32;
  3. SELECT id, customer, created FROM orders view ix_cust
  4. WHERE customer = 'Name10000'
  5. ORDER BY customer DESC, created DESC
  6. LIMIT $limit;

Stock load - 图8

To run this type of load, execute the command:

  1. ydb workload stock run getCustomerHistory [global workload options...] [specific workload options...]

Stock load - 图9

Parameters for getCustomerHistory

Parameter nameShort nameParameter description
—limit <value>-l <value>The required number of orders. Default value: 10.

getRandomCustomerHistory load

This type of load reads the specified number of orders from randomly selected customers.

YQL query:

  1. DECLARE $cust AS Utf8;
  2. DECLARE $limit AS UInt32;
  3. SELECT id, customer, created FROM orders view ix_cust
  4. WHERE customer = $cust
  5. ORDER BY customer DESC, created DESC
  6. LIMIT $limit;

Stock load - 图10

To run this type of load, execute the command:

  1. ydb workload stock run getRandomCustomerHistory [global workload options...] [specific workload options...]

Stock load - 图11

Parameters for getRandomCustomerHistory

Parameter nameShort nameParameter description
—limit <value>-l <value>The required number of orders. Default: 10.

insertRandomOrder load

This type of load creates a randomly generated order. The order includes several different products, 1 item per product. The number of products in the order is generated randomly based on an exponential distribution.

YQL query:

  1. DECLARE $ido AS UInt64;
  2. DECLARE $cust AS Utf8;
  3. DECLARE $lines AS List<Struct<product:Utf8,quantity:Int64>>;
  4. DECLARE $time AS DateTime;
  5. INSERT INTO `orders`(id, customer, created) VALUES
  6. ($ido, $cust, $time);
  7. UPSERT INTO `orderLines`(id_order, product, quantity)
  8. SELECT $ido, product, quantity FROM AS_TABLE( $lines );

Stock load - 图12

To run this type of load, execute the command:

  1. ydb workload stock run insertRandomOrder [global workload options...] [specific workload options...]

Stock load - 图13

Parameters for insertRandomOrder

Parameter nameShort nameParameter description
—products <value>-p <value>Number of products in the test. The default value is 100.

submitRandomOrder load

This type of load creates a randomly generated order and processes it. The order includes several different products, 1 item per product. The number of products in the order is generated randomly based on an exponential distribution. Order processing consists in decreasing the number of ordered products in stock.

YQL query:

  1. DECLARE $ido AS UInt64;
  2. DECLARE $cust AS Utf8;
  3. DECLARE $lines AS List<Struct<product:Utf8,quantity:Int64>>;
  4. DECLARE $time AS DateTime;
  5. INSERT INTO `orders`(id, customer, created) VALUES
  6. ($ido, $cust, $time);
  7. UPSERT INTO `orderLines`(id_order, product, quantity)
  8. SELECT $ido, product, quantity FROM AS_TABLE( $lines );
  9. $prods = SELECT * FROM orderLines AS p WHERE p.id_order = $ido;
  10. $cnt = SELECT COUNT(*) FROM $prods;
  11. $newq =
  12. SELECT
  13. p.product AS product,
  14. COALESCE(s.quantity, 0) - p.quantity AS quantity
  15. FROM $prods AS p
  16. LEFT JOIN stock AS s
  17. ON s.product = p.product;
  18. $check = SELECT COUNT(*) AS cntd FROM $newq as q WHERE q.quantity >= 0;
  19. UPSERT INTO stock
  20. SELECT product, quantity FROM $newq WHERE $check=$cnt;
  21. $upo = SELECT id, $time AS tm FROM orders WHERE id = $ido AND $check = $cnt;
  22. UPSERT INTO orders SELECT id, tm AS processed FROM $upo;
  23. SELECT * FROM $newq AS q WHERE q.quantity < 0

Stock load - 图14

To run this type of load, execute the command:

  1. ydb workload stock run submitRandomOrder [global workload options...] [specific workload options...]

Stock load - 图15

Parameters for submitRandomOrder

Parameter nameShort nameParameter description
—products <value>-p <value>Number of products in the test. The default value is 100.

submitSameOrder load

This type of load creates an order with the same set of products and processes it. Order processing consists in decreasing the number of ordered products in stock.

YQL query:

  1. DECLARE $ido AS UInt64;
  2. DECLARE $cust AS Utf8;
  3. DECLARE $lines AS List<Struct<product:Utf8,quantity:Int64>>;
  4. DECLARE $time AS DateTime;
  5. INSERT INTO `orders`(id, customer, created) VALUES
  6. ($ido, $cust, $time);
  7. UPSERT INTO `orderLines`(id_order, product, quantity)
  8. SELECT $ido, product, quantity FROM AS_TABLE( $lines );
  9. $prods = SELECT * FROM orderLines AS p WHERE p.id_order = $ido;
  10. $cnt = SELECT COUNT(*) FROM $prods;
  11. $newq =
  12. SELECT
  13. p.product AS product,
  14. COALESCE(s.quantity, 0) - p.quantity AS quantity
  15. FROM $prods AS p
  16. LEFT JOIN stock AS s
  17. ON s.product = p.product;
  18. $check = SELECT COUNT(*) as cntd FROM $newq AS q WHERE q.quantity >= 0;
  19. UPSERT INTO stock
  20. SELECT product, quantity FROM $newq WHERE $check=$cnt;
  21. $upo = SELECT id, $time AS tm FROM orders WHERE id = $ido AND $check = $cnt;
  22. UPSERT INTO orders SELECT id, tm AS processed FROM $upo;
  23. SELECT * FROM $newq AS q WHERE q.quantity < 0

Stock load - 图16

To run this type of load, execute the command:

  1. ydb workload stock run submitSameOrder [global workload options...] [specific workload options...]

Stock load - 图17

Parameters for submitSameOrder

Parameter nameShort nameParameter description
—products <value>-p <value>Number of products per order. The default value is 100.

Examples of running the loads

  • Run the load insertRandomOrder for 5 seconds across 10 threads with 1000 products.
  1. ydb workload stock run insertRandomOrder -s 5 -t 10 -p 1000

Stock load - 图18

Possible result:

  1. Elapsed Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms)
  2. 1 132 0 0 69 108 132 157
  3. 2 157 0 0 63 88 97 104
  4. 3 156 0 0 62 84 104 120
  5. 4 160 0 0 62 77 90 94
  6. 5 174 0 0 61 77 97 100
  7. Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms)
  8. 779 155.8 0 0 62 89 108 157

Stock load - 图19

  • Run the submitSameOrder load for 5 seconds across 5 threads with 2 products per order, printing out only final results.
  1. ydb workload stock run submitSameOrder -s 5 -t 5 -p 1000 --quiet

Stock load - 图20

Possible result:

  1. Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms)
  2. 16 3.2 67 3 855 1407 1799 1799

Stock load - 图21

  • Run the getRandomCustomerHistory load for 5 seconds across 100 threads, printing out time for each time window.
  1. ydb workload stock run getRandomCustomerHistory -s 5 -t 10 --print-timestamp

Stock load - 图22

Possible result:

  1. Elapsed Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms) Timestamp
  2. 1 1046 0 0 7 16 25 50 2022-02-08T17:47:26Z
  3. 2 1070 0 0 7 17 22 28 2022-02-08T17:47:27Z
  4. 3 1041 0 0 7 17 22 28 2022-02-08T17:47:28Z
  5. 4 1045 0 0 7 17 23 31 2022-02-08T17:47:29Z
  6. 5 998 0 0 8 18 23 42 2022-02-08T17:47:30Z
  7. Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms)
  8. 5200 1040 0 0 8 17 23 50

Stock load - 图23

Interpretation of results

  • Elapsed: Time window ID. By default, a time window is 1 second.
  • Txs/sec: Number of successful load transactions in the time window.
  • Retries: The number of repeat attempts to execute the transaction by the client in the time window.
  • Errors: The number of errors that occurred in the time window.
  • p50(ms): 50th percentile of request latency, in ms.
  • p95(ms): 95th percentile of request latency, in ms.
  • p99(ms): 99th percentile of request latency, in ms.
  • pMax(ms): 100th percentile of request latency, in ms.
  • Timestamp: Timestamp of the end of the time window.