mysqlslapのGo版みたいなものを書いた

qrnである程度知見がたまったのでmysqlslapのGo版みたいなものを書いた。

github.com

単純なワークロードのタイプを指定できて、実行するクエリを自動生成できるやつ。 生成するクエリはmysqlslapと大体おなじような感じで、以下のような違いがある。

  • レートリミットがかけられる。逆に「何回クエリを実行」というオプションはない
  • 自動生成するクエリは実行時に生成してメモリにロードしない
    • qpsが100万とか1000万とかになったら問題になるかも
  • 結果レポートがJSON
  • --auto-generate-sql-load-typereadはフルスキャンでユースケースが少なそうだったので実装しない

Usage

$ qlap -dsn root:@/ -nagents 3 -rate 100 -time 10 \
    -auto-generate-sql -auto-generate-sql-load-type mixed \
    -number-int-cols 3 -number-char-cols 3

のような感じでコマンドを実行すると

  • 並列数: 3
  • qpsの上限: 100
  • テスト時間は10秒
  • SQLは自動生成
  • ワークロードはselect(key)とinsertを1:1
  • intのカラム数: 3
  • varcharのカラム数: 3

という感じでDBとテーブル作って負荷テストを実行する。

こういうクエリが流れる。

2021-04-05T11:57:18.491610Z        56 Query     CREATE DATABASE `qlap`
2021-04-05T11:57:18.492202Z        56 Query     USE `qlap`
2021-04-05T11:57:18.492378Z        56 Query     CREATE TABLE t1 (id SERIAL, intcol1 INT(32), intcol2 INT(32), intcol3 INT(32),
charcol1 VARCHAR(128), charcol2 VARCHAR(128), charcol3 VARCHAR(128))
2021-04-05T11:57:18.519544Z        56 Query     INSERT INTO t1 VALUES (NULL,953375677,1345621682,2029700311,'JHmVynWl3FRBBtwlDo
xiXUEYEQUSG5YMXbXR23Rns191q0sNlLVxfc9luZ7OLtxROpkYozAZv6A8ZqOWdRrUhzwyqbegL1Fq9Zi7eEbckVbsp8g0pyhkzfbfOwUXHBsX','nBDEKISedaPGFi
JCJj7kbb9J3LhPScGbzXaXDnettwnNBYrfxYyLyUluhawZND12s6PwOwwVWrYlLpeo413y6oMk3mfCyxyF4XZwcGvxjMHMt81vSrVXePUJuXv6OaMP','7YVykjuPnG
ltArdBpy7SS16aJeaxRCzEqeqrkZRPymJTDjkPRzJkJYm6WRLtT0CNTuBW8HNODJmD7W2jz386cg6TcZDbR88pQNXSRXN4HjgNh16wyVRXMu12YxRJM8rU')
2021-04-05T11:57:18.520344Z        56 Query     INSERT INTO t1 VALUES (NULL,411811214,1348318636,684257996,'Tys207WxUhcK1v8jXAs
...
2021-04-05T11:57:18.543225Z        61 Query     SELECT 'agent(0) start: token=bf9716b4-c9c8-4539-9295-701cc46daa21'
2021-04-05T11:57:18.543263Z        62 Query     SELECT 'agent(1) start: token=bf9716b4-c9c8-4539-9295-701cc46daa21'
2021-04-05T11:57:18.543301Z        60 Query     SELECT intcol1,intcol2,intcol3,charcol1,charcol2,charcol3 FROM t1 WHERE id = 60
2021-04-05T11:57:18.543337Z        61 Query     SELECT intcol1,intcol2,intcol3,charcol1,charcol2,charcol3 FROM t1 WHERE id = 77
2021-04-05T11:57:18.543359Z        62 Query     SELECT intcol1,intcol2,intcol3,charcol1,charcol2,charcol3 FROM t1 WHERE id = 8
2021-04-05T11:57:18.553569Z        61 Query     INSERT INTO t1 VALUES (NULL,440504017,1314478656,374979147,'BwukJykBzxQ7GazScoB

結果レポートは以下のような感じ。

{
  "StartedAt": "2021-04-05T20:47:48.122543+09:00",
  "FinishedAt": "2021-04-05T20:47:58.140224+09:00",
  "ElapsedTime": 10,
  "NAgents": 3,
  "Rate": 100,
  "AutoGenerateSql": true,
  "NumberPrePopulatedData": 100,
  "DropExistingDatabase": false,
  "Engine": "",
  "LoadType": "mixed",
  "NumberSecondaryIndexes": 0,
  "CommitRate": 0,
  "NumberIntCols": 3,
  "IntColsIndex": false,
  "NumberCharCols": 3,
  "CharColsIndex": false,
  "Query": "",
  "PreQueries": null,
  "Token": "bf9716b4-c9c8-4539-9295-701cc46daa21",
  "Queries": 2930,
  "QPS": 292.4863396144265,
  "MaxQPS": 305,
  "MinQPS": 202,
  "MedianQPS": 303,
  "ExpectedQPS": 300,
  "Response": {
    "Time": {
      "Cumulative": "1.70378355s",
      "HMean": "499.554µs",
      "Avg": "581.496µs",
      "P50": "535.414µs",
      "P75": "703.491µs",
      "P95": "951.235µs",
      "P99": "1.224525ms",
      "P999": "3.198177ms",
      "Long5p": "1.242647ms",
      "Short5p": "249.39µs",
      "Max": "7.235566ms",
      "Min": "145.575µs",
      "Range": "7.089991ms",
      "StdDev": "274.566µs"
    },
    "Rate": {
      "Second": 1719.7020126177413
    },
    "Samples": 2930,
    "Count": 2930,
    "Histogram": [
      {
        "145µs - 854µs": 2610
      },
      {
        "854µs - 1.563ms": 312
      },
      {
        "1.563ms - 2.272ms": 1
      },
      {
        "2.272ms - 2.981ms": 1
      },
      {
        "2.981ms - 3.69ms": 5
      },
      {
        "3.69ms - 4.399ms": 1
      },
      {
        "4.399ms - 5.108ms": 0
      },
      {
        "5.108ms - 5.817ms": 0
      },
      {
        "5.817ms - 6.526ms": 0
      }
    ]
  }
}

mysqlslapを使っているなら、同じ感覚で使えると思う。