Basic performance tests on github.

This also adds a slighly modified sysbench to the repository, which
creates encrypted tables, and modifies the debug message default to 0.
pull/209/head
Zsolt Parragi 2 years ago
parent 7f8974bd56
commit e53fc3e276
  1. 121
      .github/workflows/postgresql-16-src-meson-perf.yml
  2. 51
      .github/workflows/postgresql-perf-results.yml
  3. 6
      src/include/pg_tde_defines.h
  4. 56
      sysbench/bulk_insert.lua
  5. 503
      sysbench/oltp_common.lua
  6. 503
      sysbench/oltp_common_tde.lua
  7. 34
      sysbench/oltp_delete.lua
  8. 65
      sysbench/oltp_insert.lua
  9. 34
      sysbench/oltp_point_select.lua
  10. 57
      sysbench/oltp_read_only.lua
  11. 65
      sysbench/oltp_read_write.lua
  12. 30
      sysbench/oltp_update_index.lua
  13. 30
      sysbench/oltp_update_non_index.lua
  14. 47
      sysbench/oltp_write_only.lua
  15. 72
      sysbench/select_random_points.lua
  16. 77
      sysbench/select_random_ranges.lua

@ -0,0 +1,121 @@
name: Perf test
on: [pull_request]
permissions:
contents: write
pull-requests: write
repository-projects: write
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Remove old postgres
run: |
sudo apt purge postgresql-client-common postgresql-common \
postgresql postgresql*
sudo rm -rf /var/lib/postgresql /var/log/postgresql /etc/postgresql \
/usr/lib/postgresql /usr/include/postgresql /usr/share/postgresql \
/etc/postgresql
sudo rm -f /usr/bin/pg_config
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libreadline6-dev systemtap-sdt-dev \
zlib1g-dev libssl-dev libpam0g-dev bison flex \
libipc-run-perl -y docbook-xsl docbook-xsl libxml2 libxml2-utils \
libxml2-dev libxslt-dev xsltproc libkrb5-dev libldap2-dev \
libsystemd-dev gettext tcl-dev libperl-dev pkg-config clang-11 \
llvm-11 llvm-11-dev libselinux1-dev python3-dev \
uuid-dev liblz4-dev meson ninja-build libjson-c-dev \
sysbench
sudo /usr/bin/perl -MCPAN -e 'install IPC::RUN'
sudo /usr/bin/perl -MCPAN -e 'install Text::Trim'
- name: Clone postgres repository
uses: actions/checkout@v2
with:
repository: 'postgres/postgres'
ref: 'a81e5516fa4bc53e332cb35eefe231147c0e1749'
path: 'src'
- name: Clone postgres-tde-ext repository
uses: actions/checkout@v2
with:
path: 'src/contrib/postgres-tde-ext'
- name: Include postgres-tde-ext in meson build
run: |
echo "subdir('postgres-tde-ext')" >> src/contrib/meson.build
- name: Build postgres
run: |
meson setup build --prefix `pwd`/../inst --buildtype=release
cd build && ninja && ninja install
working-directory: src
- name: Test postgres-tde-ext
run: |
cp ../contrib/postgres-tde-ext/keyring.json /tmp/keyring.json
meson test --suite setup -v
meson test --suite postgres-tde-ext -v --num-processes 1
working-directory: src/build
- name: Report on test fail
uses: actions/upload-artifact@v2
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
path: |
src/build/testrun/postgres-tde-ext/regress/
retention-days: 3
- name: Setup test environment
run: |
bin/initdb -D data
echo "shared_preload_libraries = 'pg_tde'" >> data/postgresql.conf
echo "pg_tde.keyringConfigFile = '/tmp/keyring.json'" >> data/postgresql.conf
bin/pg_ctl -D data start
bin/createdb sbtest
bin/createdb sbtest2
bin/createuser sbtest -s
bin/psql sbtest2 <<< "CREATE EXTENSION pg_tde;"
cp -r ../src/contrib/postgres-tde-ext/sysbench .
working-directory: inst
- name: Run baseline performance tests
run: |
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_insert.lua --tables=1 --table-size=10000 --pgsql-db=sbtest prepare
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_read_only.lua --tables=1 --table-size=10000 --pgsql-db=sbtest run
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_read_only.lua --tables=1 --table-size=10000 --pgsql-db=sbtest run | tee perf_norm
working-directory: inst
- name: Run TDE performance tests
run: |
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_common_tde.lua --tables=1 --table-size=10000 --pgsql-db=sbtest2 prepare
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_read_only.lua --tables=1 --table-size=10000 --pgsql-db=sbtest2 run
sysbench --db-driver=pgsql --threads=1 sysbench/oltp_read_only.lua --tables=1 --table-size=10000 --pgsql-db=sbtest2 run | tee perf_tde
working-directory: inst
- name: Print results
run: |
NORM_Q=$(cat perf_norm | grep 'total number of events' | cut -d ':' -f 2 | sed 's/ //g')
TDE_Q=$(cat perf_tde | grep 'total number of events' | cut -d ':' -f 2 | sed 's/ //g')
echo "Norm queries: $NORM_Q"
echo "TDE queries: $TDE_Q"
echo "Performance test results:" >> pr_perf_results
echo "Normal queries: $(cat perf_norm | grep 'total number of events' | cut -d ':' -f 2 | sed 's/ //g')" >> pr_perf_results
echo "TDE queries: $(cat perf_tde | grep 'total number of events' | cut -d ':' -f 2 | sed 's/ //g')" >> pr_perf_results
echo "Percentage: $(($TDE_Q*100/$NORM_Q))%" >> pr_perf_results
PERF_RESULT=$(cat pr_perf_results)
echo "PERF_RESULT<<EOF" >> $GITHUB_ENV
echo "$PERF_RESULT" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
working-directory: inst
- uses: actions/upload-artifact@v3
with:
name: pr_perf_results
path: inst/pr_perf_results

@ -0,0 +1,51 @@
name: Perf test results
on:
workflow_run:
workflows: [Perf test]
types:
- completed
jobs:
download:
runs-on: ubuntu-latest
steps:
- name: 'Download artifact'
uses: actions/github-script@v5
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr_perf_results"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_perf_results.zip`, Buffer.from(download.data));
- name: 'Unzip artifact'
run: |
unzip pr_perf_results.zip
- name: Clone postgres-tde-ext repository
uses: actions/checkout@v2
with:
path: 'src'
ref: ${{ github.event.workflow_run.head_branch }}
- name: 'Create comment'
run: |
gh pr comment ${PR_NUMBER} -F ../pr_perf_results --edit-last || \
gh pr comment ${PR_NUMBER} -F ../pr_perf_results
env:
PR_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
working-directory: src

@ -19,9 +19,9 @@
* ---------- * ----------
*/ */
#define ENCRYPTION_DEBUG 1 #define ENCRYPTION_DEBUG 0
#define KEYRING_DEBUG 1 #define KEYRING_DEBUG 0
#define TDE_FORK_DEBUG 1 #define TDE_FORK_DEBUG 0
#define pg_tde_fill_tuple heap_fill_tuple #define pg_tde_fill_tuple heap_fill_tuple
#define pg_tde_form_tuple heap_form_tuple #define pg_tde_form_tuple heap_form_tuple

@ -0,0 +1,56 @@
#!/usr/bin/sysbench
-- -------------------------------------------------------------------------- --
-- Bulk insert benchmark: do multi-row INSERTs concurrently in --threads
-- threads with each thread inserting into its own table. The number of INSERTs
-- executed by each thread is controlled by either --time or --events.
-- -------------------------------------------------------------------------- --
cursize=0
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
end
function prepare()
local i
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = 1, sysbench.opt.threads do
print("Creating table 'sbtest" .. i .. "'...")
con:query(string.format([[
CREATE TABLE IF NOT EXISTS sbtest%d (
id INTEGER NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
PRIMARY KEY (id))]], i))
end
end
function event()
if (cursize == 0) then
con:bulk_insert_init("INSERT INTO sbtest" .. thread_id+1 .. " VALUES")
end
cursize = cursize + 1
con:bulk_insert_next("(" .. cursize .. "," .. cursize .. ")")
end
function thread_done(thread_9d)
con:bulk_insert_done()
con:disconnect()
end
function cleanup()
local i
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = 1, sysbench.opt.threads do
print("Dropping table 'sbtest" .. i .. "'...")
con:query("DROP TABLE IF EXISTS sbtest" .. i )
end
end

@ -0,0 +1,503 @@
-- Copyright (C) 2006-2018 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- -----------------------------------------------------------------------------
-- Common code for OLTP benchmarks.
-- -----------------------------------------------------------------------------
function init()
assert(event ~= nil,
"this script is meant to be included by other OLTP scripts and " ..
"should not be called directly.")
end
if sysbench.cmdline.command == nil then
error("Command is required. Supported commands: prepare, prewarm, run, " ..
"cleanup, help")
end
-- Command line options
sysbench.cmdline.options = {
table_size =
{"Number of rows per table", 10000},
range_size =
{"Range size for range SELECT queries", 100},
tables =
{"Number of tables", 1},
point_selects =
{"Number of point SELECT queries per transaction", 10},
simple_ranges =
{"Number of simple range SELECT queries per transaction", 1},
sum_ranges =
{"Number of SELECT SUM() queries per transaction", 1},
order_ranges =
{"Number of SELECT ORDER BY queries per transaction", 1},
distinct_ranges =
{"Number of SELECT DISTINCT queries per transaction", 1},
index_updates =
{"Number of UPDATE index queries per transaction", 1},
non_index_updates =
{"Number of UPDATE non-index queries per transaction", 1},
delete_inserts =
{"Number of DELETE/INSERT combinations per transaction", 1},
range_selects =
{"Enable/disable all range SELECT queries", true},
auto_inc =
{"Use AUTO_INCREMENT column as Primary Key (for MySQL), " ..
"or its alternatives in other DBMS. When disabled, use " ..
"client-generated IDs", true},
skip_trx =
{"Don't start explicit transactions and execute all queries " ..
"in the AUTOCOMMIT mode", false},
secondary =
{"Use a secondary index in place of the PRIMARY KEY", false},
create_secondary =
{"Create a secondary index in addition to the PRIMARY KEY", true},
mysql_storage_engine =
{"Storage engine, if MySQL is used", "innodb"},
pgsql_variant =
{"Use this PostgreSQL variant when running with the " ..
"PostgreSQL driver. The only currently supported " ..
"variant is 'redshift'. When enabled, " ..
"create_secondary is automatically disabled, and " ..
"delete_inserts is set to 0"}
}
-- Prepare the dataset. This command supports parallel execution, i.e. will
-- benefit from executing with --threads > 1 as long as --tables > 1
function cmd_prepare()
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
sysbench.opt.threads do
create_table(drv, con, i)
end
end
-- Preload the dataset into the server cache. This command supports parallel
-- execution, i.e. will benefit from executing with --threads > 1 as long as
-- --tables > 1
--
-- PS. Currently, this command is only meaningful for MySQL/InnoDB benchmarks
function cmd_prewarm()
local drv = sysbench.sql.driver()
local con = drv:connect()
assert(drv:name() == "mysql", "prewarm is currently MySQL only")
-- Do not create on disk tables for subsequent queries
con:query("SET tmp_table_size=2*1024*1024*1024")
con:query("SET max_heap_table_size=2*1024*1024*1024")
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
sysbench.opt.threads do
local t = "sbtest" .. i
print("Prewarming table " .. t)
con:query("ANALYZE TABLE sbtest" .. i)
con:query(string.format(
"SELECT AVG(id) FROM " ..
"(SELECT * FROM %s FORCE KEY (PRIMARY) " ..
"LIMIT %u) t",
t, sysbench.opt.table_size))
con:query(string.format(
"SELECT COUNT(*) FROM " ..
"(SELECT * FROM %s WHERE k LIKE '%%0%%' LIMIT %u) t",
t, sysbench.opt.table_size))
end
end
-- Implement parallel prepare and prewarm commands
sysbench.cmdline.commands = {
prepare = {cmd_prepare, sysbench.cmdline.PARALLEL_COMMAND},
prewarm = {cmd_prewarm, sysbench.cmdline.PARALLEL_COMMAND}
}
-- Template strings of random digits with 11-digit groups separated by dashes
-- 10 groups, 119 characters
local c_value_template = "###########-###########-###########-" ..
"###########-###########-###########-" ..
"###########-###########-###########-" ..
"###########"
-- 5 groups, 59 characters
local pad_value_template = "###########-###########-###########-" ..
"###########-###########"
function get_c_value()
return sysbench.rand.string(c_value_template)
end
function get_pad_value()
return sysbench.rand.string(pad_value_template)
end
function create_table(drv, con, table_num)
local id_index_def, id_def
local engine_def = ""
local extra_table_options = ""
local query
if sysbench.opt.secondary then
id_index_def = "KEY xid"
else
id_index_def = "PRIMARY KEY"
end
if drv:name() == "mysql" or drv:name() == "attachsql" or
drv:name() == "drizzle"
then
if sysbench.opt.auto_inc then
id_def = "INTEGER NOT NULL AUTO_INCREMENT"
else
id_def = "INTEGER NOT NULL"
end
engine_def = "/*! ENGINE = " .. sysbench.opt.mysql_storage_engine .. " */"
extra_table_options = mysql_table_options or ""
elseif drv:name() == "pgsql"
then
if not sysbench.opt.auto_inc then
id_def = "INTEGER NOT NULL"
elseif pgsql_variant == 'redshift' then
id_def = "INTEGER IDENTITY(1,1)"
else
id_def = "SERIAL"
end
else
error("Unsupported database driver:" .. drv:name())
end
print(string.format("Creating table 'sbtest%d'...", table_num))
query = string.format([[
CREATE TABLE sbtest%d(
id %s,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
%s (id)
),
table_num, id_def, id_index_def, engine_def, extra_table_options)
con:query(query)
if (sysbench.opt.table_size > 0) then
print(string.format("Inserting %d records into 'sbtest%d'",
sysbench.opt.table_size, table_num))
end
if sysbench.opt.auto_inc then
query = "INSERT INTO sbtest" .. table_num .. "(k, c, pad) VALUES"
else
query = "INSERT INTO sbtest" .. table_num .. "(id, k, c, pad) VALUES"
end
con:bulk_insert_init(query)
local c_val
local pad_val
for i = 1, sysbench.opt.table_size do
c_val = get_c_value()
pad_val = get_pad_value()
if (sysbench.opt.auto_inc) then
query = string.format("(%d, '%s', '%s')",
sb_rand(1, sysbench.opt.table_size), c_val,
pad_val)
else
query = string.format("(%d, %d, '%s', '%s')",
i, sb_rand(1, sysbench.opt.table_size), c_val,
pad_val)
end
con:bulk_insert_next(query)
end
con:bulk_insert_done()
if sysbench.opt.create_secondary then
print(string.format("Creating a secondary index on 'sbtest%d'...",
table_num))
con:query(string.format("CREATE INDEX k_%d ON sbtest%d(k)",
table_num, table_num))
end
end
local t = sysbench.sql.type
local stmt_defs = {
point_selects = {
"SELECT c FROM sbtest%u WHERE id=?",
t.INT},
simple_ranges = {
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ?",
t.INT, t.INT},
sum_ranges = {
"SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ?",
t.INT, t.INT},
order_ranges = {
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
t.INT, t.INT},
distinct_ranges = {
"SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
t.INT, t.INT},
index_updates = {
"UPDATE sbtest%u SET k=k+1 WHERE id=?",
t.INT},
non_index_updates = {
"UPDATE sbtest%u SET c=? WHERE id=?",
{t.CHAR, 120}, t.INT},
deletes = {
"DELETE FROM sbtest%u WHERE id=?",
t.INT},
inserts = {
"INSERT INTO sbtest%u (id, k, c, pad) VALUES (?, ?, ?, ?)",
t.INT, t.INT, {t.CHAR, 120}, {t.CHAR, 60}},
}
function prepare_begin()
stmt.begin = con:prepare("BEGIN")
end
function prepare_commit()
stmt.commit = con:prepare("COMMIT")
end
function prepare_for_each_table(key)
for t = 1, sysbench.opt.tables do
stmt[t][key] = con:prepare(string.format(stmt_defs[key][1], t))
local nparam = #stmt_defs[key] - 1
if nparam > 0 then
param[t][key] = {}
end
for p = 1, nparam do
local btype = stmt_defs[key][p+1]
local len
if type(btype) == "table" then
len = btype[2]
btype = btype[1]
end
if btype == sysbench.sql.type.VARCHAR or
btype == sysbench.sql.type.CHAR then
param[t][key][p] = stmt[t][key]:bind_create(btype, len)
else
param[t][key][p] = stmt[t][key]:bind_create(btype)
end
end
if nparam > 0 then
stmt[t][key]:bind_param(unpack(param[t][key]))
end
end
end
function prepare_point_selects()
prepare_for_each_table("point_selects")
end
function prepare_simple_ranges()
prepare_for_each_table("simple_ranges")
end
function prepare_sum_ranges()
prepare_for_each_table("sum_ranges")
end
function prepare_order_ranges()
prepare_for_each_table("order_ranges")
end
function prepare_distinct_ranges()
prepare_for_each_table("distinct_ranges")
end
function prepare_index_updates()
prepare_for_each_table("index_updates")
end
function prepare_non_index_updates()
prepare_for_each_table("non_index_updates")
end
function prepare_delete_inserts()
prepare_for_each_table("deletes")
prepare_for_each_table("inserts")
end
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
-- Create global nested tables for prepared statements and their
-- parameters. We need a statement and a parameter set for each combination
-- of connection/table/query
stmt = {}
param = {}
for t = 1, sysbench.opt.tables do
stmt[t] = {}
param[t] = {}
end
-- This function is a 'callback' defined by individual benchmark scripts
prepare_statements()
end
-- Close prepared statements
function close_statements()
for t = 1, sysbench.opt.tables do
for k, s in pairs(stmt[t]) do
stmt[t][k]:close()
end
end
if (stmt.begin ~= nil) then
stmt.begin:close()
end
if (stmt.commit ~= nil) then
stmt.commit:close()
end
end
function thread_done()
close_statements()
con:disconnect()
end
function cleanup()
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = 1, sysbench.opt.tables do
print(string.format("Dropping table 'sbtest%d'...", i))
con:query("DROP TABLE IF EXISTS sbtest" .. i )
end
end
local function get_table_num()
return sysbench.rand.uniform(1, sysbench.opt.tables)
end
local function get_id()
return sysbench.rand.default(1, sysbench.opt.table_size)
end
function begin()
stmt.begin:execute()
end
function commit()
stmt.commit:execute()
end
function execute_point_selects()
local tnum = get_table_num()
local i
for i = 1, sysbench.opt.point_selects do
param[tnum].point_selects[1]:set(get_id())
stmt[tnum].point_selects:execute()
end
end
local function execute_range(key)
local tnum = get_table_num()
for i = 1, sysbench.opt[key] do
local id = get_id()
param[tnum][key][1]:set(id)
param[tnum][key][2]:set(id + sysbench.opt.range_size - 1)
stmt[tnum][key]:execute()
end
end
function execute_simple_ranges()
execute_range("simple_ranges")
end
function execute_sum_ranges()
execute_range("sum_ranges")
end
function execute_order_ranges()
execute_range("order_ranges")
end
function execute_distinct_ranges()
execute_range("distinct_ranges")
end
function execute_index_updates()
local tnum = get_table_num()
for i = 1, sysbench.opt.index_updates do
param[tnum].index_updates[1]:set(get_id())
stmt[tnum].index_updates:execute()
end
end
function execute_non_index_updates()
local tnum = get_table_num()
for i = 1, sysbench.opt.non_index_updates do
param[tnum].non_index_updates[1]:set_rand_str(c_value_template)
param[tnum].non_index_updates[2]:set(get_id())
stmt[tnum].non_index_updates:execute()
end
end
function execute_delete_inserts()
local tnum = get_table_num()
for i = 1, sysbench.opt.delete_inserts do
local id = get_id()
local k = get_id()
param[tnum].deletes[1]:set(id)
param[tnum].inserts[1]:set(id)
param[tnum].inserts[2]:set(k)
param[tnum].inserts[3]:set_rand_str(c_value_template)
param[tnum].inserts[4]:set_rand_str(pad_value_template)
stmt[tnum].deletes:execute()
stmt[tnum].inserts:execute()
end
end
-- Re-prepare statements if we have reconnected, which is possible when some of
-- the listed error codes are in the --mysql-ignore-errors list
function sysbench.hooks.before_restart_event(errdesc)
if errdesc.sql_errno == 2013 or -- CR_SERVER_LOST
errdesc.sql_errno == 2055 or -- CR_SERVER_LOST_EXTENDED
errdesc.sql_errno == 2006 or -- CR_SERVER_GONE_ERROR
errdesc.sql_errno == 2011 -- CR_TCP_CONNECTION
then
close_statements()
prepare_statements()
end
end

@ -0,0 +1,503 @@
-- Copyright (C) 2006-2018 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- -----------------------------------------------------------------------------
-- Common code for OLTP benchmarks.
-- -----------------------------------------------------------------------------
function init()
assert(event ~= nil,
"this script is meant to be included by other OLTP scripts and " ..
"should not be called directly.")
end
if sysbench.cmdline.command == nil then
error("Command is required. Supported commands: prepare, prewarm, run, " ..
"cleanup, help")
end
-- Command line options
sysbench.cmdline.options = {
table_size =
{"Number of rows per table", 10000},
range_size =
{"Range size for range SELECT queries", 100},
tables =
{"Number of tables", 1},
point_selects =
{"Number of point SELECT queries per transaction", 10},
simple_ranges =
{"Number of simple range SELECT queries per transaction", 1},
sum_ranges =
{"Number of SELECT SUM() queries per transaction", 1},
order_ranges =
{"Number of SELECT ORDER BY queries per transaction", 1},
distinct_ranges =
{"Number of SELECT DISTINCT queries per transaction", 1},
index_updates =
{"Number of UPDATE index queries per transaction", 1},
non_index_updates =
{"Number of UPDATE non-index queries per transaction", 1},
delete_inserts =
{"Number of DELETE/INSERT combinations per transaction", 1},
range_selects =
{"Enable/disable all range SELECT queries", true},
auto_inc =
{"Use AUTO_INCREMENT column as Primary Key (for MySQL), " ..
"or its alternatives in other DBMS. When disabled, use " ..
"client-generated IDs", true},
skip_trx =
{"Don't start explicit transactions and execute all queries " ..
"in the AUTOCOMMIT mode", false},
secondary =
{"Use a secondary index in place of the PRIMARY KEY", false},
create_secondary =
{"Create a secondary index in addition to the PRIMARY KEY", true},
mysql_storage_engine =
{"Storage engine, if MySQL is used", "innodb"},
pgsql_variant =
{"Use this PostgreSQL variant when running with the " ..
"PostgreSQL driver. The only currently supported " ..
"variant is 'redshift'. When enabled, " ..
"create_secondary is automatically disabled, and " ..
"delete_inserts is set to 0"}
}
-- Prepare the dataset. This command supports parallel execution, i.e. will
-- benefit from executing with --threads > 1 as long as --tables > 1
function cmd_prepare()
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
sysbench.opt.threads do
create_table(drv, con, i)
end
end
-- Preload the dataset into the server cache. This command supports parallel
-- execution, i.e. will benefit from executing with --threads > 1 as long as
-- --tables > 1
--
-- PS. Currently, this command is only meaningful for MySQL/InnoDB benchmarks
function cmd_prewarm()
local drv = sysbench.sql.driver()
local con = drv:connect()
assert(drv:name() == "mysql", "prewarm is currently MySQL only")
-- Do not create on disk tables for subsequent queries
con:query("SET tmp_table_size=2*1024*1024*1024")
con:query("SET max_heap_table_size=2*1024*1024*1024")
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
sysbench.opt.threads do
local t = "sbtest" .. i
print("Prewarming table " .. t)
con:query("ANALYZE TABLE sbtest" .. i)
con:query(string.format(
"SELECT AVG(id) FROM " ..
"(SELECT * FROM %s FORCE KEY (PRIMARY) " ..
"LIMIT %u) t",
t, sysbench.opt.table_size))
con:query(string.format(
"SELECT COUNT(*) FROM " ..
"(SELECT * FROM %s WHERE k LIKE '%%0%%' LIMIT %u) t",
t, sysbench.opt.table_size))
end
end
-- Implement parallel prepare and prewarm commands
sysbench.cmdline.commands = {
prepare = {cmd_prepare, sysbench.cmdline.PARALLEL_COMMAND},
prewarm = {cmd_prewarm, sysbench.cmdline.PARALLEL_COMMAND}
}
-- Template strings of random digits with 11-digit groups separated by dashes
-- 10 groups, 119 characters
local c_value_template = "###########-###########-###########-" ..
"###########-###########-###########-" ..
"###########-###########-###########-" ..
"###########"
-- 5 groups, 59 characters
local pad_value_template = "###########-###########-###########-" ..
"###########-###########"
function get_c_value()
return sysbench.rand.string(c_value_template)
end
function get_pad_value()
return sysbench.rand.string(pad_value_template)
end
function create_table(drv, con, table_num)
local id_index_def, id_def
local engine_def = ""
local extra_table_options = ""
local query
if sysbench.opt.secondary then
id_index_def = "KEY xid"
else
id_index_def = "PRIMARY KEY"
end
if drv:name() == "mysql" or drv:name() == "attachsql" or
drv:name() == "drizzle"
then
if sysbench.opt.auto_inc then
id_def = "INTEGER NOT NULL AUTO_INCREMENT"
else
id_def = "INTEGER NOT NULL"
end
engine_def = "/*! ENGINE = " .. sysbench.opt.mysql_storage_engine .. " */"
extra_table_options = mysql_table_options or ""
elseif drv:name() == "pgsql"
then
if not sysbench.opt.auto_inc then
id_def = "INTEGER NOT NULL"
elseif pgsql_variant == 'redshift' then
id_def = "INTEGER IDENTITY(1,1)"
else
id_def = "SERIAL"
end
else
error("Unsupported database driver:" .. drv:name())
end
print(string.format("Creating table 'sbtest%d'...", table_num))
query = string.format([[
CREATE TABLE sbtest%d(
id %s,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
%s (id)
) USING pg_tde %s %s]],
table_num, id_def, id_index_def, engine_def, extra_table_options)
con:query(query)
if (sysbench.opt.table_size > 0) then
print(string.format("Inserting %d records into 'sbtest%d'",
sysbench.opt.table_size, table_num))
end
if sysbench.opt.auto_inc then
query = "INSERT INTO sbtest" .. table_num .. "(k, c, pad) VALUES"
else
query = "INSERT INTO sbtest" .. table_num .. "(id, k, c, pad) VALUES"
end
con:bulk_insert_init(query)
local c_val
local pad_val
for i = 1, sysbench.opt.table_size do
c_val = get_c_value()
pad_val = get_pad_value()
if (sysbench.opt.auto_inc) then
query = string.format("(%d, '%s', '%s')",
sb_rand(1, sysbench.opt.table_size), c_val,
pad_val)
else
query = string.format("(%d, %d, '%s', '%s')",
i, sb_rand(1, sysbench.opt.table_size), c_val,
pad_val)
end
con:bulk_insert_next(query)
end
con:bulk_insert_done()
if sysbench.opt.create_secondary then
print(string.format("Creating a secondary index on 'sbtest%d'...",
table_num))
con:query(string.format("CREATE INDEX k_%d ON sbtest%d(k)",
table_num, table_num))
end
end
local t = sysbench.sql.type
local stmt_defs = {
point_selects = {
"SELECT c FROM sbtest%u WHERE id=?",
t.INT},
simple_ranges = {
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ?",
t.INT, t.INT},
sum_ranges = {
"SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ?",
t.INT, t.INT},
order_ranges = {
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
t.INT, t.INT},
distinct_ranges = {
"SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
t.INT, t.INT},
index_updates = {
"UPDATE sbtest%u SET k=k+1 WHERE id=?",
t.INT},
non_index_updates = {
"UPDATE sbtest%u SET c=? WHERE id=?",
{t.CHAR, 120}, t.INT},
deletes = {
"DELETE FROM sbtest%u WHERE id=?",
t.INT},
inserts = {
"INSERT INTO sbtest%u (id, k, c, pad) VALUES (?, ?, ?, ?)",
t.INT, t.INT, {t.CHAR, 120}, {t.CHAR, 60}},
}
function prepare_begin()
stmt.begin = con:prepare("BEGIN")
end
function prepare_commit()
stmt.commit = con:prepare("COMMIT")
end
function prepare_for_each_table(key)
for t = 1, sysbench.opt.tables do
stmt[t][key] = con:prepare(string.format(stmt_defs[key][1], t))
local nparam = #stmt_defs[key] - 1
if nparam > 0 then
param[t][key] = {}
end
for p = 1, nparam do
local btype = stmt_defs[key][p+1]
local len
if type(btype) == "table" then
len = btype[2]
btype = btype[1]
end
if btype == sysbench.sql.type.VARCHAR or
btype == sysbench.sql.type.CHAR then
param[t][key][p] = stmt[t][key]:bind_create(btype, len)
else
param[t][key][p] = stmt[t][key]:bind_create(btype)
end
end
if nparam > 0 then
stmt[t][key]:bind_param(unpack(param[t][key]))
end
end
end
function prepare_point_selects()
prepare_for_each_table("point_selects")
end
function prepare_simple_ranges()
prepare_for_each_table("simple_ranges")
end
function prepare_sum_ranges()
prepare_for_each_table("sum_ranges")
end
function prepare_order_ranges()
prepare_for_each_table("order_ranges")
end
function prepare_distinct_ranges()
prepare_for_each_table("distinct_ranges")
end
function prepare_index_updates()
prepare_for_each_table("index_updates")
end
function prepare_non_index_updates()
prepare_for_each_table("non_index_updates")
end
function prepare_delete_inserts()
prepare_for_each_table("deletes")
prepare_for_each_table("inserts")
end
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
-- Create global nested tables for prepared statements and their
-- parameters. We need a statement and a parameter set for each combination
-- of connection/table/query
stmt = {}
param = {}
for t = 1, sysbench.opt.tables do
stmt[t] = {}
param[t] = {}
end
-- This function is a 'callback' defined by individual benchmark scripts
prepare_statements()
end
-- Close prepared statements
function close_statements()
for t = 1, sysbench.opt.tables do
for k, s in pairs(stmt[t]) do
stmt[t][k]:close()
end
end
if (stmt.begin ~= nil) then
stmt.begin:close()
end
if (stmt.commit ~= nil) then
stmt.commit:close()
end
end
function thread_done()
close_statements()
con:disconnect()
end
function cleanup()
local drv = sysbench.sql.driver()
local con = drv:connect()
for i = 1, sysbench.opt.tables do
print(string.format("Dropping table 'sbtest%d'...", i))
con:query("DROP TABLE IF EXISTS sbtest" .. i )
end
end
local function get_table_num()
return sysbench.rand.uniform(1, sysbench.opt.tables)
end
local function get_id()
return sysbench.rand.default(1, sysbench.opt.table_size)
end
function begin()
stmt.begin:execute()
end
function commit()
stmt.commit:execute()
end
function execute_point_selects()
local tnum = get_table_num()
local i
for i = 1, sysbench.opt.point_selects do
param[tnum].point_selects[1]:set(get_id())
stmt[tnum].point_selects:execute()
end
end
local function execute_range(key)
local tnum = get_table_num()
for i = 1, sysbench.opt[key] do
local id = get_id()
param[tnum][key][1]:set(id)
param[tnum][key][2]:set(id + sysbench.opt.range_size - 1)
stmt[tnum][key]:execute()
end
end
function execute_simple_ranges()
execute_range("simple_ranges")
end
function execute_sum_ranges()
execute_range("sum_ranges")
end
function execute_order_ranges()
execute_range("order_ranges")
end
function execute_distinct_ranges()
execute_range("distinct_ranges")
end
function execute_index_updates()
local tnum = get_table_num()
for i = 1, sysbench.opt.index_updates do
param[tnum].index_updates[1]:set(get_id())
stmt[tnum].index_updates:execute()
end
end
function execute_non_index_updates()
local tnum = get_table_num()
for i = 1, sysbench.opt.non_index_updates do
param[tnum].non_index_updates[1]:set_rand_str(c_value_template)
param[tnum].non_index_updates[2]:set(get_id())
stmt[tnum].non_index_updates:execute()
end
end
function execute_delete_inserts()
local tnum = get_table_num()
for i = 1, sysbench.opt.delete_inserts do
local id = get_id()
local k = get_id()
param[tnum].deletes[1]:set(id)
param[tnum].inserts[1]:set(id)
param[tnum].inserts[2]:set(k)
param[tnum].inserts[3]:set_rand_str(c_value_template)
param[tnum].inserts[4]:set_rand_str(pad_value_template)
stmt[tnum].deletes:execute()
stmt[tnum].inserts:execute()
end
end
-- Re-prepare statements if we have reconnected, which is possible when some of
-- the listed error codes are in the --mysql-ignore-errors list
function sysbench.hooks.before_restart_event(errdesc)
if errdesc.sql_errno == 2013 or -- CR_SERVER_LOST
errdesc.sql_errno == 2055 or -- CR_SERVER_LOST_EXTENDED
errdesc.sql_errno == 2006 or -- CR_SERVER_GONE_ERROR
errdesc.sql_errno == 2011 -- CR_TCP_CONNECTION
then
close_statements()
prepare_statements()
end
end

@ -0,0 +1,34 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Delete-Only OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
prepare_for_each_table("deletes")
end
function event()
local tnum = sysbench.rand.uniform(1, sysbench.opt.tables)
local id = sysbench.rand.default(1, sysbench.opt.table_size)
param[tnum].deletes[1]:set(id)
stmt[tnum].deletes:execute()
end

@ -0,0 +1,65 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Insert-Only OLTP benchmark
-- ----------------------------------------------------------------------
require(".oltp_common")
sysbench.cmdline.commands.prepare = {
function ()
if (not sysbench.opt.auto_inc) then
-- Create empty tables on prepare when --auto-inc is off, since IDs
-- generated on prepare may collide later with values generated by
-- sysbench.rand.unique()
sysbench.opt.table_size=0
end
cmd_prepare()
end,
sysbench.cmdline.PARALLEL_COMMAND
}
function prepare_statements()
-- We do not use prepared statements here, but oltp_common.sh expects this
-- function to be defined
end
function event()
local table_name = "sbtest" .. sysbench.rand.uniform(1, sysbench.opt.tables)
local k_val = sysbench.rand.default(1, sysbench.opt.table_size)
local c_val = get_c_value()
local pad_val = get_pad_value()
if (drv:name() == "pgsql" and sysbench.opt.auto_inc) then
con:query(string.format("INSERT INTO %s (k, c, pad) VALUES " ..
"(%d, '%s', '%s')",
table_name, k_val, c_val, pad_val))
else
if (sysbench.opt.auto_inc) then
i = 0
else
-- Convert a uint32_t value to SQL INT
i = sysbench.rand.unique() - 2147483648
end
con:query(string.format("INSERT INTO %s (id, k, c, pad) VALUES " ..
"(%d, %d, '%s', '%s')",
table_name, i, k_val, c_val, pad_val))
end
end

@ -0,0 +1,34 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- OLTP Point Select benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
-- use 1 query per event, rather than sysbench.opt.point_selects which
-- defaults to 10 in other OLTP scripts
sysbench.opt.point_selects=1
prepare_point_selects()
end
function event()
execute_point_selects()
end

@ -0,0 +1,57 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Read-Only OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
prepare_point_selects()
if not sysbench.opt.skip_trx then
prepare_begin()
prepare_commit()
end
if sysbench.opt.range_selects then
prepare_simple_ranges()
prepare_sum_ranges()
prepare_order_ranges()
prepare_distinct_ranges()
end
end
function event()
if not sysbench.opt.skip_trx then
begin()
end
execute_point_selects()
if sysbench.opt.range_selects then
execute_simple_ranges()
execute_sum_ranges()
execute_order_ranges()
execute_distinct_ranges()
end
if not sysbench.opt.skip_trx then
commit()
end
end

@ -0,0 +1,65 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Read/Write OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
if not sysbench.opt.skip_trx then
prepare_begin()
prepare_commit()
end
prepare_point_selects()
if sysbench.opt.range_selects then
prepare_simple_ranges()
prepare_sum_ranges()
prepare_order_ranges()
prepare_distinct_ranges()
end
prepare_index_updates()
prepare_non_index_updates()
prepare_delete_inserts()
end
function event()
if not sysbench.opt.skip_trx then
begin()
end
execute_point_selects()
if sysbench.opt.range_selects then
execute_simple_ranges()
execute_sum_ranges()
execute_order_ranges()
execute_distinct_ranges()
end
execute_index_updates()
execute_non_index_updates()
execute_delete_inserts()
if not sysbench.opt.skip_trx then
commit()
end
end

@ -0,0 +1,30 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Update-Index OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
prepare_index_updates()
end
function event()
execute_index_updates(con)
end

@ -0,0 +1,30 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Update-Non-Index OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
prepare_non_index_updates()
end
function event()
execute_non_index_updates()
end

@ -0,0 +1,47 @@
#!/usr/bin/sysbench
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Write-Only OLTP benchmark
-- ----------------------------------------------------------------------
require("oltp_common")
function prepare_statements()
if not sysbench.opt.skip_trx then
prepare_begin()
prepare_commit()
end
prepare_index_updates()
prepare_non_index_updates()
prepare_delete_inserts()
end
function event()
if not sysbench.opt.skip_trx then
begin()
end
execute_index_updates()
execute_non_index_updates()
execute_delete_inserts()
if not sysbench.opt.skip_trx then
commit()
end
end

@ -0,0 +1,72 @@
#!/usr/bin/sysbench
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
require("oltp_common")
-- Add random_points to the list of standard OLTP options
sysbench.cmdline.options.random_points =
{"Number of random points in the IN() clause in generated SELECTs", 10}
-- Override standard prepare/cleanup OLTP functions, as this benchmark does not
-- support multiple tables
oltp_prepare = prepare
oltp_cleanup = cleanup
function prepare()
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
"--tables > 1")
oltp_prepare()
end
function cleanup()
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
"--tables > 1")
oltp_cleanup()
end
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
local points = string.rep("?, ", sysbench.opt.random_points - 1) .. "?"
stmt = con:prepare(string.format([[
SELECT id, k, c, pad
FROM sbtest1
WHERE k IN (%s)
]], points))
params = {}
for j = 1, sysbench.opt.random_points do
params[j] = stmt:bind_create(sysbench.sql.type.INT)
end
stmt:bind_param(unpack(params))
rlen = sysbench.opt.table_size / sysbench.opt.threads
thread_id = sysbench.tid % sysbench.opt.threads
end
function thread_done()
stmt:close()
con:disconnect()
end
function event()
-- To prevent overlapping of our range queries we need to partition the whole
-- table into 'threads' segments and then make each thread work with its
-- own segment.
for i = 1, sysbench.opt.random_points do
local rmin = rlen * thread_id
local rmax = rmin + rlen
params[i]:set(sb_rand(rmin, rmax))
end
stmt:execute()
end

@ -0,0 +1,77 @@
#!/usr/bin/sysbench
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
require("oltp_common")
-- Add --number-of-ranges and --delta to the list of standard OLTP options
sysbench.cmdline.options.number_of_ranges =
{"Number of random BETWEEN ranges per SELECT", 10}
sysbench.cmdline.options.delta =
{"Size of BETWEEN ranges", 5}
-- Override standard prepare/cleanup OLTP functions, as this benchmark does not
-- support multiple tables
oltp_prepare = prepare
oltp_cleanup = cleanup
function prepare()
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
"--tables > 1")
oltp_prepare()
end
function cleanup()
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
"--tables > 1")
oltp_cleanup()
end
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
local ranges = string.rep("k BETWEEN ? AND ? OR ",
sysbench.opt.number_of_ranges - 1) ..
"k BETWEEN ? AND ?"
stmt = con:prepare(string.format([[
SELECT count(k)
FROM sbtest1
WHERE %s]], ranges))
params = {}
for j = 1, sysbench.opt.number_of_ranges*2 do
params[j] = stmt:bind_create(sysbench.sql.type.INT)
end
stmt:bind_param(unpack(params))
rlen = sysbench.opt.table_size / sysbench.opt.threads
thread_id = sysbench.tid % sysbench.opt.threads
end
function thread_done()
stmt:close()
con:disconnect()
end
function event()
-- To prevent overlapping of our range queries we need to partition the whole
-- table into 'threads' segments and then make each thread work with its
-- own segment.
for i = 1, sysbench.opt.number_of_ranges*2, 2 do
local rmin = rlen * thread_id
local rmax = rmin + rlen
local val = sb_rand(rmin, rmax)
params[i]:set(val)
params[i+1]:set(val + sysbench.opt.delta)
end
stmt:execute()
end
Loading…
Cancel
Save