새소식

MySQL & Maria

성능테스트 SYSBENCH CUSTOM SCRIPT

  • -
반응형
SYSBENCH 란 ? 

sysbench는 LUA 스크립트를 이용하고 multi-thread 방식을 지원한느 벤치마크 툴로써 MySQL / MariaDB와 같은 Database에서 주로 사용되는 오픈소스 벤치마킹 프로그램이다.

sysbench를 통해 QPS / TPS를 측정할 수 있다.

 

INSTALL

SYSBENCH는  YUM을 통하여 설치가 가능하다.

yun -y install epel-release
yum -y install sysbench

 

SYSBENCH CUSTOM SCRIPT

1) SYSBECNH API

  • sysbench의 핵심 API 3개가 필요하다 Thread_init, thread_done, event
  • execute_inserts() ⇒ insert시 사용하는 문구로 select만 필요하기때문에 제거
-- Called by sysbench one time to initialize this script
function thread_init()

  -- Create globals to be used elsewhere in the script

  -- drv - initialize the sysbench mysql driver
  drv = sysbench.sql.driver()

  -- con - represents the connection to MySQL
  con = drv:connect()
end

-- Called by sysbench when script is done executing

function thread_done()
  -- Disconnect/close connection to MySQL
  con:disconnect()
end


-- Called by sysbench for each execution
function event()

  -- If user requested to disable transactions,
  -- do not execute BEGIN statement
  if not sysbench.opt.skip_trx then
    con:query("BEGIN")
  end

  -- Run our custom statements
  execute_selects()
 -- execute_inserts() -- IF insert TEST 

  -- Like above, if transactions are disabled,
  -- do not execute COMMIT
  if not sysbench.opt.skip_trx then
    con:query("COMMIT")
  end
end

 

2) 온전성 검사 및 옵션

  • 첫 번째 섹션은 사용자가 실제로 이 테스트를 실행하기를 원하는지 확인하기 위한 온전성 검사입니다. 위에서 언급한 다른 테스트 스크립트는  prepare, run 및 cleanup 과 같은 명령을 지원합니다. 우리의 스크립트는  우리가 사용하는 데이터가 핵심 애플리케이션에 의해 미리 채워져 있기 때문에 실행만 지원합니다.
  • 두 번째 섹션에서는 스크립트 작성자가 사용자가 테스트 스크립트에 특정한 몇 가지 옵션을 전달할 수 있도록 합니다. 위의 코드에서 각 **스레드/반복에서 실행될 SELECT 문의 수에 대한 옵션(기본값은 5)**을 볼 수 있으며 다른 옵션을 사용하면 사용자가 원하는 경우 BEGIN/COMMIT를 비활성화할 수 있습니다(기본값은 false ). 스크립트에서 더 많은 사용자 정의를 원하면 더 많은 옵션을 추가하기만 하면 됩니다. 나중에 이러한 매개변수를 참조하는 방법을 볼 수 있습니다.
if sysbench.cmdline.command == nil then
   error("Command is required. Supported commands: run")
end

sysbench.cmdline.options = {
  point_selects = {"Number of point SELECT queries to run", 5},
  skip_trx = {"Do not use BEGIN/COMMIT; Use global auto_commit value", false}
}

 

3) Query

  • TEST에 사용할 Query
  • 아래 문구들은 TEST Query 문구이며 나의 경우 Select만 TEST할 예정이어서 필요 없는 구문들은 TEST LUA에선 삭제했다.
-- Array of categories to be use in the INSERTs
local page_types = { "actor", "character", "movie" }
 
-- Array of COUNT(*) queries
local select_counts = {
  "SELECT COUNT(*) FROM imdb.title"
}
 
-- Array of SELECT statements that have 1 integer parameter
local select_points = {
  "SELECT * FROM imdb.title WHERE id = %d",
  "SELECT * FROM imdb.comments ORDER BY id DESC limit 10",
  "SELECT AVG(rating) avg FROM imdb.movie_ratings WHERE movie_id = %d",
  "SELECT * FROM imdb.users ORDER BY RAND() LIMIT 1"
}
 
-- Array of SELECT statements that have 1 string parameter
local select_string = {
  "SELECT * FROM imdb.title WHERE title LIKE '%s%%'"
}
 
-- INSERT statements
local inserts = {
  "INSERT INTO imdb.users (email_address, first_name, last_name) VALUES ('%s', '%s', '%s')",
  "INSERT INTO imdb.page_views (type, viewed_id, user_id) VALUES ('%s', %d, %d)"
}

 

4) 구문 분석 ( SELECT 문 )

  • SELECT FUNCTION
  • 위의 select query에 대해 for 문 루프를 볼 수 있다.
  • point_selects ⇒ 한 Thread에서 몇번 반복할지 온전성 검사 및 옵션 부분 확인
function execute_selects()
 
  -- Execute each simple, no parameters, SELECT
  for i, o in ipairs(select_counts) do
    con:query(o)
  end
	
  -- Loop for however many queries the
  -- user wants to execute in this category
  for i = 1, sysbench.opt.point_selects do
	
    -- select random query from list
    local randQuery = select_points[math.random(#select_points)]
	
    -- generate random id and execute
    local id = sysbench.rand.pareto(1, 3000000)
    con:query(string.format(randQuery, id))
  end
	
  -- generate random string and execute
  for i, o in ipairs(select_string) do
    local str = sysbench.rand.string(string.rep("@", sysbench.rand.special(2, 15)))
    con:query(string.format(o, str))
  end
 
end

 

5) 구문 분석 ( INSERT 구문 )

  • INSERT  문에는 값이 필요합니다 . 다시 말하지만, sysbench는 각 반복의 이벤트에서  execute_inserts 함수를 호출합니다. execute_inserts 내부에서 위에서 설명한 내장 함수를 사용
function create_random_email()
  local username = sysbench.rand.string(string.rep("@",sysbench.rand.uniform(5,10)))
  local domain = sysbench.rand.string(string.rep("@",sysbench.rand.uniform(5,10)))
  return username .. "@" .. domain .. ".com"
end
 
function execute_inserts()
 
  -- generate fake email/info
  local email = create_random_email()
  local firstname = sysbench.rand.string("first-" .. string.rep("@", sysbench.rand.special(2, 15)))
  local lastname = sysbench.rand.string("last-" .. string.rep("@", sysbench.rand.special(2, 15)))
 
  -- INSERT for new imdb.user
  con:query(string.format(inserts[1], email, firstname, lastname))
 
  -- INSERT for imdb.page_view
  local page = page_types[math.random(#page_types)]
  con:query(string.format(inserts[2], page, sysbench.rand.special(2, 500000), sysbench.rand.special(2, 500000)))
 
end

 

6) 실제 SELECT TEST LUA 파일

  • 대부분 SELECT 관련 QUERY에 대해 TEST를 할예정이라 SELECT FUNCTION만 사용하였음
  • 한 Thread 당 반복은 5번 ( point_selects = {"Number of point SELECT queries to run", 5}, )
  • lee_query => 실제 TEST할떄 사용할 Query
[root@tobe-mysql8 sysbench]# cat select.lua
-- Called by sysbench one time to initialize this script
function thread_init()

  -- Create globals to be used elsewhere in the script

  -- drv - initialize the sysbench mysql driver
  drv = sysbench.sql.driver()

  -- con - represents the connection to MySQL
  con = drv:connect()
end

-- Called by sysbench when script is done executing
function thread_done()
  -- Disconnect/close connection to MySQL
  con:disconnect()
end

-- Called by sysbench for each execution
function event()

  -- If user requested to disable transactions,
  -- do not execute BEGIN statement
  if not sysbench.opt.skip_trx then
    con:query("BEGIN")
  end

  -- Run our custom statements
  execute_selects()

  -- Like above, if transactions are disabled,
  -- do not execute COMMIT
  if not sysbench.opt.skip_trx then
    con:query("COMMIT")
  end
end

if sysbench.cmdline.command == nil then
   error("Command is required. Supported commands: run")
end

sysbench.cmdline.options = {
  point_selects = {"Number of point SELECT queries to run", 5},
  skip_trx = {"Do not use BEGIN/COMMIT; Use global auto_commit value", false}
}

lee_query = { "select * from employees where emp_no > 20000 and first_name like 'F%'" }

function execute_selects()

  -- Execute each simple, no parameters, SELECT
  for i, o in ipairs(lee_query) do
    con:query(o)
  end
  for i = 1, sysbench.opt.point_selects do
  end
end

 

Execution

100개의 Thread가 TEST Query ( lee_query )를 5번씩 실행하도록 하는 LUA SCRIPT를 실행하였다.

[root@tobe-mysql8 sysbench]# sysbench select.lua --mysql-user=sysbench --mysql-password=sysbench --mysql-db=employees --threads=100 --mysql-socket=/tmp/mysql.sock  --debug run
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 100
Debug mode enabled.

Initializing random number generator from current time


Initializing worker threads...

DEBUG: Worker thread (#0) started
(생략)
DEBUG: Worker thread (#97) initialized
DEBUG: Worker thread (#91) initialized
DEBUG: Worker thread (#95) initialized
DEBUG: Worker thread (#96) initialized
DEBUG: Worker thread (#98) initialized
DEBUG: Worker thread (#92) initialized
DEBUG: Worker thread (#99) initialized
Threads started!

Time limit exceeded, exiting...
(last message repeated 99 times)
Done.

SQL statistics:
    queries performed:
        read:                            313
        write:                           0
        other:                           626
        total:                           939
    transactions:                        313    (28.74 per sec.)
    queries:                             939    (86.21 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          10.8898s
    total number of events:              313

Latency (ms):
         min:                                  837.52
         avg:                                 3296.21
         max:                                 4234.27
         95th percentile:                     3841.98
         sum:                              1031712.98

Threads fairness:
    events (avg/stddev):           3.1300/0.34
    execution time (avg/stddev):   10.3171/0.29

DEBUG: Verbose per-thread statistics:

DEBUG:     thread #  0: min: 0.8386s  avg: 2.6966s  max: 3.3805s  events: 4
DEBUG:                  total time taken by event execution: 10.7862s
DEBUG:     thread #  1: min: 1.2487s  avg: 2.7191s  max: 3.3571s  events: 4
(생략)
DEBUG:     thread # 99: min: 2.9913s  avg: 3.5344s  max: 3.8349s  events: 3
DEBUG:                  total time taken by event execution: 10.6032s

 

참고

https://www.percona.com/blog/2019/04/25/creating-custom-sysbench-scripts/

 

Creating Custom Sysbench Scripts - Percona Database Performance Blog

You can write your own Lua scripts to harness the power of load-testing, benchmarking, and results analysis with sysbench. Matthew Boehm shows you how.

www.percona.com

 

반응형

'MySQL & Maria' 카테고리의 다른 글

ProxySQL 성능 테스트  (0) 2022.09.22
MHA 구성 - MySQL ( Using Ansible )  (0) 2022.09.22
[Maria] Galera Cluster to Single DB(DR)  (0) 2022.05.07
[ Maria ] DDL시 Replication Delay 발생  (0) 2022.04.26
[ MySQL ] Online DDL - Varchar  (0) 2022.04.12
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.