NOC 2013 Rails에서의 Parameterized Query의 구현

Page 1

Rails에서의 Parameterized query의 구현 RailsでのParameterized queryの実装 Rails도입후의 성능 저하와 그 해결 방법(Oracle binding)의 소개 Rails導入後のOracle binding問題に起因するパフォーマンスの低下とそ の解決方法の紹介

Junichiro Kasuya GameOn Co. Ltd.

[Ruby on Rails도입후의 Oracle binding문제에 기인하는 퍼포먼스의 저하와 그 해결 방법의 소개] [Ruby on Rails導入後のOracle binding問題に起因するパフォーマンスの低下とその解決方法の紹介]


자기소개 / 自己紹介

 

Game on @Tokyo Web Programmer, 공통Library작성(共通Library作成) a. Trouble shooting b. Development Pmang.jp (Game portal)

I love motorbike


오늘 이야기 / きょうのはなし  Rails(v2.x) & SqlRelay & Oracle사용시의 Bottle-neck (Rails(v2.x)&SQLRelay&Oracle使用時のボトルネック)

 Bottle-neck의 해결 방법 (ボトルネックの解決方法)

 벤치마크 (実装後の効果)


 Rails(v2.x) & SqlRelay & Oracle사용시의 Bottle-neck현상 (Rails(v2.x)&SQLRelay&Oracle使用時のボトルネック)


보틀넥의 조사 / ボトルネックの調査 경위 /経緯

 모 신규 게임 타이틀을 Game portal에 도입 예정 (某新規ゲームタイトルをGame portalへ追加したい。) a. b.

현재의 Game portal사용자에 3∼4배의 사용자를 예상하고 있다. (現在のGame portalユーザーの3~4倍のユーザーを想定している。) 가능한 일인지 조사 해 달라 (問題ないか調査してほしい。)

 Game portal system조사 착수 (Game portal system調査へ)


Bottle-neck의 조사 / ボトルネックの調査 Game Portal System Overview

Game Portal Web

Middle ware

DB

Ruby on Rails ASP/PHP

Memcached SQLRelay Redis

SQLServer

Oracle

Scale out パフォーマンスが足りないため Scale out

GameServer GameDB GameServer GameDB GameServer

GameDB

Scale out(X) 라이센스 비용 발생 Scale outするためのライセンス 費用が高い


Bottle-neck의 조사 / ボトルネックの調査 DB팀에서 (DBチームより)

 Rails 도입 이 후 바인딩이 이루어지지 않고 있다. RailsになってからパラメータのBind機構を使用していない。

 HARD PARSE가 대량으로 발생하고 있기 때문에 성능 저하 된다. HARD PARSEが大量に発生しているためパフォーマンスが出ない。


Bottle-neck의 조사 / ボトルネックの調査 파라미터의 바인딩? / パラメータのバインド機構とは?

 리터럴의 경우(バインド機構を使わない場合) a. select userid from member where usn = 10000; b. select userid from member where usn = 10001;

DB입장에선 다른 쿼리 違うクエリ

 바인딩의 경우(バインド機構を使う場合) a. select userid from member where usn = :a0; @a0 = 10000 b. select userid from member where usn = :a0; @a0 = 10001

파라메터화 같은 쿼리로 인식 パラメータ化 同じクエリ


Bottle-neck의 조사 / ボトルネックの調査 바인딩의 영향 / バインド機構の影響 

여기서 Oracle의 쿼리 해석에 있어서 파라메터의 바인딩이 어떤 영향을 주는지 설명 하겠습니다. ここでOracleのクエリ解析においてパラメータのバインド機構が どのような影響があるか説明いたします。

이 도표는 Oracle Database의 쿼리 해석의 흐름을 간략화 한 것입니다. この図はOracle Databaseでの クエリ解析の流れを図にしたものです。

Library cache

cache Parse

Cursor Cache

Miss

Soft Parse

Miss

Hard Parse

Hit Library cache Execute Hit Cursor Cache


Bottle-neck의 조사 / ボトルネックの調査 바인드 변수를 사용하지 않을 경우 / バインド機構を使わない場合 

바인드 변수를 사용하지 않을 경우, library cache에 같은 SQL문장의 캐쉬가 있을 확률이 낮아지기 때문에 대부분의 SQL에 대하여 Hard Parse가 이루어 집니다. バインド機構を使わない場合、library cacheに同じSQL文のキャッシュがある 可能性が低くなるためほとんどのSQLに対してHard Parseが行われます。 실행 계획 등 (자원 소모 증가)

Library cache

実行計画の作成など (重い)

cache Parse

Cursor Cache

Miss

Soft Parse

Miss

Hard Parse

Hit Library cache Execute Hit Cursor Cache


보틀넥의 조사 / ボトルネックの調査 바인드 변수를 사용 할 경우 / バインド機構を利用する場合 

바인드 변수를 이용할 경우, library cache에 같은 SQL문장의 캐쉬가 있을 가능성이 높아지기 때문에, Soft Parse만으로 해석이 이루어 집니다. バインド機構を利用する場合、library cacheに同じSQL文のキャッシュがある 可能性が高くなるため、Soft Parseまでで解析が完了します。

Hard Parse를 하지 않으므로, 비교적 가벼움 Hard Parseを通さないので、 比較的軽い

Library cache

cache Parse

Cursor Cache

Miss

Soft Parse

Miss

Hard Parse

Hit Library cache Execute Hit Cursor Cache


 Bottle-neck현상의 해결 방법 (바인드 변수 사용) ボトルネックの解決方法(Railsでバインド)


Bottle-neck현상의 해결 방법 / ボトルネックの解決方法 Rails에서 DB로의 쿼리 송신 / RailsからDBへクエリを送信する流れ 

이 도표는 Rails에서 DB에 쿼리를 송신 할 때까지의 흐름을 간략화 한 것 입니다. この図はRailsでのApplicationから DBにクエリを送信するまでの 概略図です。 Application으로부터 발행한 명령은 ActiveRecord를 통해서, RAW Query가 되어, DB에 전달됩니다. Applicationから発行した命令は ActiveRecord を通して、RAW Queryになり、DBへ渡されます。

User.find(…) Application

Application

Model

Model

ActiveRecord Adapter select userid from member where usn = …

SQLRelay

DB


Bottle-neck의 해결 방법 / ボトルネックの解決方法 방법 1: RAW Query를 던지도록 어플리케이션 코드를 수정 方法1: アプリケーション側でRAW Queryに書き換える。

User.find(10000) ↓ User.connection.execute( "select * from member where usn = :a0", {:a0 => 10000} )

Application

Application

Model

Model

ActiveRecord Adapter

 문제점 / 問題点 a.

b.

회사내의 모든 Rails Application을 수정하는 것은 유지보수가 힘들어 진다. 会社内の全てのRails Applicationを書き換えるのは保守性 が低下する。

프로젝트 진행 중에 튀는 사람이 발생할지도... プロジェクト進行中に逃げ出す人が発生しそう。

SQLRelay

DB


Bottle-neck의 해결 방법 / ボトルネックの解決方法 방법 2: Adapter 측에서 Literal value를 Parameter화 한다 方法2: ドライバ側でLiteral valueをParameter化する。 Adapter 단계에선 RAW Query 상태가 되므로, literal value를 parameter화 AdapterにはRAW Queryが渡ってくるので、 literal valueをparameter化 select * from member where usn = 10000 ↓ select * from member where usn = :a0 (:a0 = 10000)

Application

Application

Model

Model

ActiveRecord Adapter

 메리트 / メリット a.

Application의 Adapter만 변경해도 된다.

全てのApplicationのAdapterを置き換えるだけでよい。 b. Application 개발자 입장에선 공짜 점심. Application開発者から見ると自動解決

SQLRelay

DB


Bottle-neck의 해결 방법 / ボトルネックの解決方法 쿼리의 Literal value 치환 방법 クエリのLiteral valueを置き換える方法 select userid from member where usn = 10000 select userid from member where userid = 'ab'

Racc에서 구문 분석 Raccで構文解析


Bottle-neck의 해결 방법 / ボトルネックの解決方法 구문 분석 / 構文解析

 용도 / 用途 a.

b.

구조를 가진 텍스트의 처리를 한다. 構造をもったテキストの処理を行う。 컴파일러 등에서 사용되고 있다. コンパイラなどで使われている。

Text (Source)

구문 분석 構文解析

Syntax tree

Object code


Bottle-neck의 해결 방법 / ボトルネックの解決方法 구문 분석 / 構文解析

 어떤 일을 하고 있는 것인가? / どんなことをしているのか? 크게 2단계에 나눌 수 있습니다. / 大きく2段階に分けられます。 a. b.

구문 해석 / 字句解析( Lexical Analysis ) 문장 해석 / 構文解析( Syntax Analysis )


Bottle-neck의 해결 방법 / ボトルネックの解決方法 구문 해석 / 字句解析( Lexical Analysis )  문자열을 Token으로 나눈 다음 파서에 넘겨 준다. 文字列からTokenに分け、次の構文解析器に渡す。 SELECT, select SYMBOL, userid FROM, from select userid from member where usn = 10000

SYMBOL, member WHERE, where SYMBOL, usn OPERATOR, = NUMBER, 10000


Bottle-neck의 해결 방법 / ボトルネックの解決方法 문장 해석 / 構文解析( Syntax Analysis )

SELECT, select SYMBOL, userid

미리 준비해 둔 룰에 근거하여, 문법의 체크와 {} 안의 처리를 한다. 予め書いたルールに基づいて、文法のチェックと {} 内の処理を実行する。

FROM, from

SYMBOL, member WHERE, where

rule sql_stmt: select_stmt {..} | update_stmt {..}

SYMBOL, usn

select_stmt: SELECT select_column FROM table_name ..

OPERATOR, =

select_column: SYMBOL {..}

NUMBER, 10000

table_name: SYMBOL {...}


Bottle-neck의 해결 방법 / ボトルネックの解決方法 문장 해석 / 構文解析( Syntax Analysis )

SELECT, select SYMBOL, userid FROM, from

SYMBOL, member WHERE, where SYMBOL, usn OPERATOR, = NUMBER, 10000

rule sql_stmt: select_stmt {..} | update_stmt {..} ..... where_conditions: WHERE condition {..} condition: column_name OPERATOR number_litteral {..} ...... number_literal: NUMBER { result = add_binding_param(val[0]) }


Bottle-neck의 해결 방법 / ボトルネックの解決方法 작성한 라이브러리의 동작 확인 / 作成したライブラリの動作確認

[Source] •

[Result]

원래의 쿼리 10000이 :a0로 바뀌고, a0의 파라미터는 10000로 추출 된 것을 확인 할 수 있습니다. 元のクエリの10000が:a0に書き換わり、a0のパラメータは10000と取り出せました。 このライブラリをAdapterへ組み込みました。


Bottle-neck의 해결 방법 / ボトルネックの解決方法 Rails의 Adapter(SQLRelayAdapter)에 구현 RailsのAdapter(SQLRelayAdapter)へ実装  주안점  파싱 실패가 서비스장애로 이어지지 않도록   

Parse실패 시에 Raw Query를 실행 DB에서 Query Error가 발생하면, Raw Query를 재실행 설정으로 기능을 On / Off 가능하도록

 実装時に注意したこと  失敗しても以前と同じように動くことを念頭に a. b. c.

Parse失敗時にRawQueryを再投入 DBでQueryErrorが発生したら、RawQuery再投入 設定ファイルでdisableにすることができる


 벤치마크 / 実装後の効果


벤치마크 実装後の効果 [A]Oracle Database의 경우 / あるOracle databaseでは

900,000

Hard parse의 비율이 16% -> 0.27%(1/59)이 되었습니다. Hard parseの割合が 16% -> 0.27%(1/59)になりました。 Statistic parse count (describe) parse count (failures) parse count (hard) parse count (total) parse time cpu parse time elapsed hard parse parcentage

4月15日 13 194 840,864 5,243,447 162612 164,757 16.03%

4月16日 58 206 838057 5,224,406 162398 163,657 16.04%

4月17日 3 260 14,649 1,726,491 6234 7,699 0.83%

4月18日 1 179 4,812 1,706,908 4,622 5,786 0.27%

800,000 700,000 600,000 500,000

parse count (hard)

400,000

parse time cpu

300,000

parse time elapsed

200,000

100,000 0

4月15日

4月16日

4月17日

4月18日


実装後の効果

벤치마크 実装後の効果 [B]Oracle Database의 경우 / もう一方の複雑なデータが入っているdatabaseでは

이쪽은 그다지 성능이 향상되지 않았습니다. (Hard parse가 ½정도 줄어들었다) 이 DB는 JOIN/MERGE 등 파서가 대응하지 않는 쿼리가 많은 것이 원인.

100,000 90,000 80,000

こちらはそれほどパフォーマンスが上がりませんでした。 (Hard parseが1/2ぐらいに減った) このDBはJOIN/MERGEなどライブラリが対応していない クエリが多かったことが判明。 Statistic parse count (describe) parse count (failures) parse count (hard) parse count (total) parse time cpu parse time elapsed hard parse parcentage

4月15日 0 10,464 89,088 588,078 27,067 27,720 13.37%

4月16日 0 9,263 81,057 559,751 23,220 23,423 12.83%

4月17日 0 2,808 34,678 445,349 12,303 13,624 7.16%

70,000 60,000

parse count (hard)

50,000 4月18日 0 2,087 24,786 366,512 8,989 9,105 6.19%

parse time cpu

40,000

parse time elapsed

30,000 20,000 10,000 0

4月15日 4月16日 4月17日 4月18日


정리 / まとめ  Rails에서 바인드 변수를 사용 함으로써 Oracle의 성능을 개선했습니다.  Rails3에서는 Primary key에서의 select는 바인딩을 사용하고 있습니다.  적용한 라이브러리는 Primary key 이외의 쿼리도 바인딩을 지원합니다.

 RailsでBinding機構を使うことにより Oracleのパフォーマンス改善ができました。  Rails3ではPrimary keyでのselectはBind機構使ってるようです。  今回のライブラリではprimary key以外のクエリもBind機構が使えるようになっています。


감사합니다. ご静聴ありがとうございました。


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.