VimでNeomake + Pylavaを使用したPython3の自動静的コード解析

はじめに

Python3のコーディングをVimで行う際にPEP8規約違反などを自動的に検出する方法をまとめます。

静的検証ツール Pylava の導入

Pythonの静的解析ツール Pylava を使用します。

github.com

Pylava では pycodestylePyFlakes などのツール群が利用可能であるため強力なコードチェックが可能です。
同様のツールとして Pylama がありますが、現状Python3.7に未対応です。
そこで Pylama からフォークした Pylava を選択しました。

github.com

github.com

Pylava では例えば次のような検証ができます。

  • pycodestyle : コードのPEP8規約準拠
  • pydocstyle : docstring のPEP257規約準拠
  • pyflakes : 論理的なエラー検知(未使用のモジュールや未定義の名前など)
  • Maccabe : McCabeの複雑度

インストール

$ pip install pylava

Pylavaの設定

pylava は実行時にカレントディレクトリから設定ファイルを探します。
pylava.ini を作成することで使用するlinterや無視する規約などを指定することができます。 pydocstyle はデフォルトだと無効なので明示的に記述する必要があります。

pylava.ini

[pylava]
skip = */settings.py
linters = pycodestyle,pydocstyle,pyflakes,mccabe
ignore = D203,D213,D401,D406

個人設定では ignore には以下のエラーコードを指定しています。
PEP257では規約内で矛盾が生じている箇所があるため個人の好みやプロジェクト内のルールに従い選択が必要です。

エラーコード エラーメッセージ
D203 1 blank line required before class docstring
D213 Multi-line docstring summary should start at the second line
D401 First line should be in imperative mood
D406 Section name should end with a newline

Pylavaの動作確認

例として次のサンプルプログラムを用意します。
使用していない sys のimportが行われている等の不備に気付くかと思います。

sample.py

import sys

def plus(a, b):
    print(a + b)

plus(1,2)

sample.py は1と2を足して3を出力するだけの単純なプログラムです。

$ python sample.py 
3

このままでも実行可能ですが、 pylava を実行することで改善点が多々あることが検知できます。

$ pylava
sample.py:1:1: D100 Missing docstring in public module [pydocstyle]
sample.py:1:1: W0611 'sys' imported but unused [pyflakes]
sample.py:3:1: E302 expected 2 blank lines, found 1 [pycodestyle]
sample.py:3:1: D103 Missing docstring in public function [pydocstyle]
sample.py:6:1: E305 expected 2 blank lines after class or function definition, found 1 [pycodestyle]
sample.py:6:7: E231 missing whitespace after ',' [pycodestyle]

VimでPylavaを自動実行

Neomakeの導入

コーディング後に都度 pylava を実行するのは手間なのでVim上で自動的にエラー検知を可能にします。 pylavaの自動実行にはVimプラグイン neomake を使用します。

github.com

dein.toml

[[plugins]]
repo = 'neomake/neomake'

Neomakeの設定

Neovimの場合は .init.vimVimの場合は .vimrcNeomake から Pylava を使用するための設定を記述します。

.init.vim(.vimrc)

call neomake#config#set('ft.python.pylama.exe', 'pylava')
call neomake#configure#automake('nrwi', 100)
let g:neomake_open_list = 2
let g:neomake_python_enabled_makers = ['pylama']
let g:neomake_python_pylama_maker = {
        \ 'args': ['--format', 'parsable', '-o', '~/pylava.ini'],
        \ 'errorformat': '%f:%l:%c: [%t] %m',
        \ 'postprocess': function('neomake#makers#ft#python#PylamaEntryProcess'),
        \ 'output_stream': 'stdout',
        \ 'exe': '/usr/local/bin/pylava'
        \ }

特に注意が必要な点として、 pylava を 使用するためには次の設定が必要です。

.init.vim(.vimrc)

call neomake#config#set('ft.python.pylama.exe', 'pylava')

github.com

また前述の pylava.iniVimからも共有したいので、 args には pylava -o ~/pylava.ini を指定しています(設定ファイルのパスは適宜変更してください)。

.init.vim(.vimrc)

let g:neomake_python_pylama_maker = {
        \ 'args': ['--format', 'parsable', '-o', '~/pylava.ini'],
        ...

exe には pylava のパスを指定します。
conda などで導入してある pylava を使用したい場合にもこちらで指定が可能です。

.init.vim(.vimrc)

let g:neomake_python_pylama_maker = {
        ...
        \ 'exe': '/usr/local/bin/pylava'
        \ }

エラーの一覧はロケーションリストに出力されるため、 エラー箇所への移動を簡単にするためにマッピングを設定します。

.init.vim(.vimrc)

map <C-n> :lnext<CR>
map <C-p> :lprev<CR>

動作確認

このようにしてVimから離れることなくコードの質を高めることができます。

f:id:hiroki-sawano:20181111145649g:plain

Miniconda3でPython環境構築

はじめに

本エントリではMinicondaでPython環境を構築する手順をまとめます。

インストール

Miniconda3 Python 3.7 version(投稿時点最新Ver 4.5.11)を次の手順で導入します。

  1. 次のURLにアクセス : https://conda.io/miniconda.html
  2. 該当するOSのbashインストーラをダウンロード
  3. インストーラを実行 : $ bash Miniconda3-latest-<your_operating_system>-x86_64.sh

Conda環境の作成

$  conda create --name sample-env
Solving environment: done

## Package Plan ##

  environment location: /Users/.../miniconda3/envs/sample-env

Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate sample-env
#
# To deactivate an active environment, use
#
#     $ conda deactivate

Conda環境のアクティベート

$ conda activate sample-env
(sample-env) $ 

環境設定ファイルの作成

conda installpip install でインストールしたパッケージを含めて環境設定を持ち運びたい場合は conda env export で環境情報をエクスポートします。

$ conda env export > environment.yml

例えば次のようなymlファイルが出力されます。

environment.yml

name: sample-env
channels:
  - conda-forge
  - ...
dependencies:
  - factory_boy=2.11.1=py_0
  - faker=0.9.2=py36_1000
  - text-unidecode=1.2=py_0
  - blas=1.0=mkl
  - bzip2=1.0.6=h1de35cc_5
  - ...
  - pip:
    - atomicwrites==1.2.1
    - attrs==18.2.0
    - beautifulsoup4==4.6.3
    - coverage==4.5.1
    - ...
prefix: /Users/.../miniconda3/envs/sample-env

environment.yml のバージョン管理

パッケージの追加・更新を行う際は environment.yml を都度更新してgitなどでバージョン管理しておきます。 ただし、次の点に注意します。

prefixの削除

conda env export を行うと前述の通りconda環境のパスが prefix に出力されます。

environment.yml

prefix: /Users/.../miniconda3/envs/sample-env

このパスは環境依存なので prefix は削除します。
後述するymlからの環境作成時にはデフォルトの ~/miniconda3/envs/sample-env が使用されるだけで特に害はないです。

stackoverflow.com

GitHubから直接インストール

GitHubから直接パッケージをインストールしたい場合には、次の通り記述します。

environment.yml

dependencies:
  - pip:
    - "--editable=git+https://github.com/project-path/project.git#egg=project"

stackoverflow.com

ymlファイルからconda環境作成

ここまでに作成した environment.yml を入力に conda env create することで簡単にconda環境を再作成できます。

$ conda env create -f environment.yml
$ source activate sample-env

C#で非同期に処理するTask間のメッセージ通信

はじめに

C#でTaskを使用した非同期処理をする場合に複数スレッド間でメッセージのやりとりをする方法をまとめます。

実行環境

事前準備

MVVM Light ToolkitのMessengerを使用するのでNuGetでインストールします。 f:id:hiroki-sawano:20180907062443p:plain

プロキシの設定が必要な場合はNuGet.Configに次の記述を追加します。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="http_proxy" value="http://~~" />
    <add key="http_proxy.user" value="user_name" />
  </packageSources>
</configuration>

サンプルプログラムの構成

ここではTaskATaskBが並列実行している中で、TaskAがとあるイベントを契機にTaskBにメッセージを送信し、TaskBはメッセージを処理し終えたことをTaskAに通知するプログラムを想定します。 f:id:hiroki-sawano:20180907073634p:plain

実装

まずはじめにProgram::Main()で2つのTaskrun()します。

class Program
{
    static void Main(string[] args)
    {
        TaskA taskA = new TaskA();
        TaskB taskB = new TaskB();

        var tokenSource = new CancellationTokenSource();
        var token = tokenSource.Token;

        var tasks = new[]
        {
            Task.Run(() => taskA.run(token), token),
            Task.Run(() => taskB.run(token), token)
        };
        Task.WaitAll(tasks);
    }
}

続けてTask側ですが、各Taskのコンストラクタではメッセージ受信時に起動したいメソッドをMessenger.Default.Registerで登録しています。
TaskAResponseMessage型のインスタンスMessenger.Default.Sendされたときに、TaskA::onReceivedMessage(ResponseMessage res)を実行します。
TaskBRequestMessage型のインスタンスMessenger.Default.Sendされたときに、TaskB::onReceivedMessage(RequestMessage req)を実行します。
Messenger.Default.SendはメッセージをMessengerに登録している全タスクにブロードキャストしてしまうので、メッセージの型を変えることでメッセージの送信先を制御しています。

class TaskA
{
    public TaskA()
    {
        Messenger.Default.Register<ResponseMessage>(this, onReceivedMessage);
    }
    public void run(CancellationToken token)
    {
        // do something
        RequestMessage req = new RequestMessage();
        req.msg = "TaskA's message.";
        Messenger.Default.Send<RequestMessage>(req);
    }
    private void onReceivedMessage(ResponseMessage res)
    {
        Console.WriteLine("TaskB sent the following message : " + res.msg);
    }
}

class TaskB
{
    public TaskB()
    {
        Messenger.Default.Register<RequestMessage>(this, onReceivedMessage);
    }

    public void run(CancellationToken token)
    {
        //do something
    }

    private void onReceivedMessage(RequestMessage req)
    {
        Console.WriteLine("TaskA sent the following message : " + req.msg);
        ResponseMessage res = new ResponseMessage();
        res.msg = "TaskB's message.";
        Messenger.Default.Send(res);
    }
}

class RequestMessage
{
    public string msg { get; set; }
}

class ResponseMessage
{
    public string msg { get; set; }
}

さいごに

これでひとまずやりたいことはできましたが、より良い方法が見つかったら追記します。

LINE Messaging APIを使用したbotの作成

はじめに

LINE Botを作成してみたので本エントリにまとめます。

Herokuをはじめる

botアプリケーションはHerokuにデプロイするため、 こちらの手順に従ってHerokuアカウントの登録、Heroku CLIのインストールと使い方を学びます。

Herokuはアプリケーションをクラウドでビルド、実行、運用できるPaaSです。 devcenter.heroku.com

LINE Developersコンソールでチャネルを作成

LINEが提供するMessaging APIを使用したbotを作成するためには、 開発者アカウントの登録とLINEプラットフォームを使用するために必要な"チャネル"を作成する必要があります。 手順はこちらの記事にまとまっています。 qiita.com

次のようにチャネルの作成ではアプリ名を'My bot'としました。 f:id:hiroki-sawano:20180504073716p:plain

Herokuにはmy-bot-201805としてsample-spring-boot-echoをデプロイしました。 f:id:hiroki-sawano:20180504073733p:plain

これでLINEからMy botにメッセージを送ると、送信したメッセージがMy botから返ってきます。 f:id:hiroki-sawano:20180504073748p:plain

サンプルbotの修正

ここまででEchoサンプルボットの動作確認ができました。
続けて少しだけサンプルアプリsample-spring-boot-echoに手を加えてみます。

まず、Herokuからmy-bot-201805リポジトリをgitでクローンします。

$ heroku git:clone -a my-bot-201805
Cloning into 'my-bot-201805'...
warning: You appear to have cloned an empty repository.

しかし、上記に示すように空のリポジトリをクローンした、と警告されます。 この事象についてはこちらのヘルプに載っていました。
どうやらsample-spring-boot-echoのREADMEで行なったように、 Herokuボタンを使用したHeroku API経由のデプロイだとこのような結果になるようです。
Why do I see a message 'You appear to have cloned an empty repository' when using `heroku git:clone`? - Heroku Help

同ヘルプページのResolutionに従ってHerokuボタンのリンクからgitリポジトリのURLを取得し、git remote addgit pullすれば良いです。

$ cd my-bot-201805/
$ git remote add origin https://github.com/line/line-bot-sdk-java
$ git pull origin master

それではbotに修正を加えます。
以下の通り、EchoApplication::handleTextMessageEvent()に"How are you?"というメッセージを受け取った場合には"I'm great!"と応答するコードを追加します。

EchoApplication.java

@EventMapping
public TextMessage handleTextMessageEvent(MessageEvent<TextMessageContent> event) {
    System.out.println("event: " + event);
    if (event.getMessage().getText().equals("How are you?")){
        return new TextMessage("I'm great!");
    } else {
        return new TextMessage(event.getMessage().getText());
    }
}

変更を反映します。

$ git add .
$ git commit -am "Make it more interactive"
$ git push heroku master

LINEからメッセージを送ると期待通りに動作することが確認できました。 f:id:hiroki-sawano:20180504081944j:plain

さいごに

bot作成は思った以上に簡単にできることがわかりました。なかなか面白いです。
実用的なbotアプリの実装に向けてこれからアイディアを捻出してみようと思います。

Vimのmakeで任意の名前のMakefileを指定する

はじめに

Vimmakeコマンドは便利ですが、任意の名前のMakefileをオプションで指定できそうもありません (カレントディレクトリのMakefileを探しにいきます)。
そのため所属するプロジェクトでMakefileの格納先ディレクトリや命名規則が規定されている場合は不便です。

そこで本エントリではこの問題の解決策をまとめます。

問題

Cobolプログラムで説明します。
次に示す例では、cobファイルとMakefileを格納しているディレクトリが異なり、 Makefileには<PROGRAM-ID>.makといった名称をつけるルールが定められています。

$ tree
.
├── make
│   └── hello.mak
└── source
    └── hello.cob

hello.cob

       IDENTIFICATION DIVISION.
       PROGRAM-ID. HELLO.
       PROCEDURE DIVISION.
       MAIN SECTION.
           DISPLAY 'HELLO WORLD!!'.
           STOP RUN.

hello.mak

hello.o    :    hello.cob
  cobc -x --free hello.cob

このような環境においてhello.cobVimで編集中にmakeしたい時、../make/hello.makを指定する方法を考えます。

対応策

ただ単にmakeしたいだけであれば、:!make -f <makefile_name>を実行すれば良いです。
しかしこの場合、Quickfixリストが機能しないため良い解決策とは言えないでしょう。

そこでmakeprgを使用します。
makeprgを使用することで:makeを実行した時に発行されるコマンドを任意に設定することができます。

次の設定を.vimrcに追加します。
ノーマルモードでF5を押下した時にCBLCOMP関数を呼び出す(1行目)
makeprgmake -f ../make/<cob_file_name>.makを組み立てて設定(4行目〜8行目)
makeコマンドを実行(9行目)

.vimrc

001 nnoremap <F5> :call CBLCOMP()<CR>
002 
003 function! CBLCOMP()
004  let &makeprg='make -f '
005  let &makeprg.=expand('%:p:h:h')
006  let &makeprg.='/make/'
007  let &makeprg.=expand('%:t:r')
008  let &makeprg.='.mak'
009  exec ':make'
010 endfunction

これで、Vim上でF5を押すだけで編集中のプログラムに対応したMakefileを指定してmakeを実行し、make結果をQuickfixリストで確認できるようになりました。

f:id:hiroki-sawano:20180501235608p:plain
makeで構文エラーを検出した場合

Cygwinの個人的セットアップ(GNU Global + Pygments + Vim)

はじめに

自宅ではMacですが職場ではWindows7なのでターミナルで操作したいときはCygwinを使うようにしてます。 本エントリではCygwinをインストールする際に、まず始めに実施する個人的セットアップをまとめます。

Cygwinのインストール

以下のURLからCygwinインストーラーをダウンロードしてインストールします。 https://cygwin.com/install.html

インストールの過程では最低限以下のパッケージを選択します(あくまで個人的に必要なものです)。

  • gcc-core
  • libncurses-devel
  • make
  • python3
  • python3-pygments
  • vim
  • wget
  • git

パッケージ管理ツールの整備

Cygwinインストーラでもパッケージの管理が可能ですが、ターミナル上で利用可能なツール「apt-cyg」をインストールします。

wgetのプロキシ設定(必要な場合のみ)

/etc/wgetrc

 82 # You can set the default proxies for Wget to use for http, https, and ftp.
 83 # They will override the value in the environment.
 84 https_proxy = ...
 85 http_proxy = ...
 86 ftp_proxy = ...
 87 proxy_user = ...
 88 proxy_passwd = ...
 89
 90 # If you do not want to use proxy at all, set this to off.
 91 use_proxy = on

apt-cygのインストール

$ wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
$ chmod 755 apt-cyg
$ mv apt-cyg /usr/local/bin/

apt-cygでは次のようなコマンドでパッケージの管理ができます。

  • パッケージを検索
$ apt-cyg searchall <package_name>
  • インストール済みのパッケージを検索
$ apt-cyg search <package_name>
  • パッケージをインストール
$ apt-cyg install <package_name>

GNU Globalのインストール

以下のURLからglobal-6.6.2.tar.gz(2018/2/20現在最新)をダウンロードします。 http://www.gnu.org/software/global/download.html

Cygwin上で以下のコマンドを実行し、GNU Globalをインストールします。

$ tar xvf global-6.5.6.tar.gz
$ cd global-6.5.6
$ ./configure
$ make
$ make install

プラグインvimにインストール

$ mkdir -p ~/.vim/plugin
$ cp /usr/local/share/gtags/gtags.vim ~/.vim/plugin/gtags.vim

.vimrcにGtags用のショートカットを追加

.vimrcは後述するリポジトリから取得するため普段省略しますが、既に作成済みの.vimrcがある場合はGtags用に以下のマッピングを追加します。

~/.vimrc

map <C-g> :Gtags
map <C-h> :Gtags -f %<CR>
map <C-j> :GtagsCursor<CR>
map <C-n> :cn<CR>
map <C-p> :cp<CR>

PygmentsとGNU Globalの連携

以下のコマンドを実行します。

$ cp /usr/local/share/gtags/gtags.conf ~/.globalr

.globalrを以下の通り編集します。

~/.globalr
変更前

default:\
         :tc=native:

変更後

default:\
        :tc=native:tc=pygments:

(参考)gtagsの使用方法

解析対象のソースファイルを含むディレクトリ(最上位ディレクトリで良い)で以下のコマンドを実行することで タグファイルを作成できます。

$ gtags -v

以下のファイルが同ディレクトリに作成されていることが確認できます。
* GPATH
* GRTAGS
* GTAGS

これで、vimから変数名などにカーソルを合わせて<C-j>で参照関係を検索し、 <C-n>で次のファイルに移動、<C-p>で前のファイルに移動可能になります。

(参考)htagsの使用方法

htagsコマンドをタグファイルがあるディレクトリで実行することで、コードをWebブラウザで確認するためのhtmlファイルを出力できます (オプションは適宜変えて下さい)。

$ htags -safno -v --html-header=./encode_meta.html

日本語文字の文字化けを防ぐためにmetaタグの指定を--html-headerオプションで行います。 「./encode_meta.html」には以下の通り文字コードを指定します。

<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />

ドットファイルの取得

ドットファイルはgitで管理しているのでcloneします。

必要に応じて次の通りプロキシの設定を行います。

$ git config --global http.proxy http://<username>:<userpsw>@<proxy>:<port>
$ git config --global https.proxy https://<username>:<userpsw>@<proxy>:<port>

~/.gitconfig

[http]
        proxy = http://<username>:<userpsw>@<proxy>:<port>
[https]
        proxy = http://<username>:<userpsw>@<proxy>:<port>

続けて以下のリポジトリをcloneして、setup.shを実行します。 github.com

$ cd ~
$ git clone https://github.com/hiroki-sawano/dotfiles.git
$ sh ~/dotfiles/setup.sh

HiRDBで表のマトリクス分割

はじめに

データベースシステムのデータ格納方式は、性能・信頼・運用性等を考慮した上で決定する必要があります。 本エントリではこの目的において、HiRDBでデータの物理配置を制御する「表のマトリクス分割」を試してみた結果をまとめます。

表の横分割の種類

HiRDBでは表を分割して格納する場合に、大きく次の分割方法を選択できます。 このうち、今回は3点目のマトリクス分割でキーレンジ分割+FIXハッシュ分割を行います。

  • キーレンジ分割
    キーとなる値の格納条件指定または境界値指定で表を分割する。
  • ハッシュ分割
    ハッシュ関数を使用して、均等に表を複数のRDエリアに格納する。
  • マトリクス分割※
    第1次元分割列で境界値指定のキーレンジ分割をし、分割されたデータをさらに第2次元分割列で分割する。第2次元分割列には次の分割方法が指定できる。
    (a) 境界値指定のキーレンジ分割
    (b) フレキシブルハッシュ分割
    (c) FIXハッシュ分割
    ※HiRDB Advanced High Availabilityが必要

想定するシステム構成

次のように複数のRDエリアが異なるディスクのHiRDBファイルシステム領域に割り当てられている場合に、 第1次元のキーレンジ分割によって、ディスク障害時の影響範囲を局所化し(信頼性向上)、 第2次元のFIXハッシュ分割でI/Oの並列処理を可能とする(性能向上)ことが狙いです。 f:id:hiroki-sawano:20180212192455p:plain

  • FES(フロントエンドサーバ):SQLの解析/最適化処理やBESへの指示などを担うサーバ
  • BES(バックエンドサーバ):FESからの指示に従ってデータベースへのアクセスや排他制御、演算処理などを行うサーバ
  • RD_T1~4:ユーザ用RDエリア(テーブル用)
  • RD_I1~4:ユーザ用RDエリア(インデクス用)

マトリクス分割の確認

それでは実際にマトリクス分割を行う表を定義し、行挿入時に指定のRDエリアがデータ格納先として使用されることを確認します。

実行環境

  • Red Hat Enterprise Server Linux 7(64-bit)/バージョン7.3
  • HiRDB Server with Additional Function Version 9
    • HiRDB/Parallel Server Version 9.65
  • HiRDB Advanced High Availability Version 9

テーブル定義の作成

列"row_type"でキーレンジ分割し、列"id1"と列"id2でFIXハッシュ分割します。
キーレンジ分割での境界値の指定は、PARTITIONED BY MULTIDIMに続けて昇順に行います。 以下の例では'10'と指定してあるため、row_typeが'10'以下の行と'10'を超過する行がそれぞれ異なるRDエリアに分割されます。
FIXハッシュ分割では、分割キーに「キー値の偏りが少ない」、「キーの値に重複が少ない」列を選択します。 また、ハッシュ関数は複数用意されていますが、リバランス表でない場合最も均等にハッシングされるHASH6を選びます。

この定義によって次の通り動作することが期待できます。
<row_type <= '10'の場合> RD_T1とRD_T2に格納
<row_type > '10'の場合> RD_T3とRD_T4に格納

MATRIX_TEST.sql

CREATE TABLE "MATRIX_TEST" (
  "id1"          INTEGER      NOT NULL,
  "id2"          INTEGER      NOT NULL,
  "row_type"     CHAR(2)      NOT NULL,
  "row_value"    VARCHAR(100)
)
 PARTITIONED BY MULTIDIM
 ("row_type" (('10')),
 FIX HASH HASH6 BY "id1","id2")
                   IN ((RD_T1,RD_T2),
                       (RD_T3,RD_T4))
 PRIMARY KEY ("id1", "id2", "row_type")
                   IN ((RD_I1,RD_I2),
                       (RD_I3,RD_I4))
;

次の通り作成したテーブル定義のSQLを実行します。

$ pddef < ./MATRIX_TEST.sql
KFPA12000-I Processing of SQL completed
$ pdsql
COMMAND ?     +----2----+----3----+----4----+----5----+----6----+----7----+
tables;
 TABLE_SCHEMA                   TABLE_NAME                     N_COLS N_INDEX CREATE_TIME
 ------------------------------ ------------------------------ ------ ------- --------------
 xxxxxxx                        MATRIX_TEST                         4       1 20180212190159

データの挿入と表分割の確認

次のデータをMATRIX_TESTに挿入しながら、経過をDB状態解析機能(pddbst)で確認します。

SELECT * FROM MATRIX_TEST;
 id1          id2          row_type row_value
 ------------ ------------ -------- -----------------------------------------------------
            1            1 10       ABCD
            1            2 10       ABCD
            2            2 20       ABCD
            2            1 20       ABCD
KFPX27010-I            4 rows selected

作業開始前の状態確認

テーブル用ユーザRDエリアの状態確認を行っていきます。
pddbstの-tオプションで解析対象のテーブル'MATRIX_TEST'を指定します。 この時点ではどのRDエリアの使用率も0%であることがわかります(記載内容はコマンド実行結果の一部抜粋)。

$ pddbst -t MATRIX_TEST
 RD Area Name   : RD_T1
  Server        : bes1
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T2
  Server        : bes2
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T3
  Server        : bes3
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T4
  Server        : bes4
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0

row_type'10'の挿入(1行目)

RD_T1が使用されている様子が確認できます。

$ pdsql
COMMAND ?     +----2----+----3----+----4----+----5----+----6----+----7----+
INSERT INTO MATRIX_TEST VALUES (1,1,'10','ABCD');
KFPX27010-I            1 rows inserted
…
$ pddbst -t MATRIX_TEST
 RD Area Name   : RD_T1
  Server        : bes1
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T2
  Server        : bes2
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T3
  Server        : bes3
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T4
  Server        : bes4
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0

row_type'10'の挿入(2行目)

2行目の挿入ではハッシュ分割されてRD_T2が使用されました。

$ pdsql
COMMAND ?     +----2----+----3----+----4----+----5----+----6----+----7----+
INSERT INTO MATRIX_TEST VALUES (1,2,'10','ABCD');
KFPX27010-I            1 rows inserted
…
$ pddbst -t MATRIX_TEST
 RD Area Name   : RD_T1
  Server        : bes1
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T2
  Server        : bes2
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T3
  Server        : bes3
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T4
  Server        : bes4
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0

row_type'20'の挿入(1行目)

キー値を'20'にするとRD_T4にデータが格納されました。

$ pdsql
COMMAND ?     +----2----+----3----+----4----+----5----+----6----+----7----+
INSERT INTO MATRIX_TEST VALUES (2,1,'20','ABCD');
KFPX27010-I            1 rows inserted
…
$ pddbst -t MATRIX_TEST
 RD Area Name   : RD_T1
  Server        : bes1
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T2
  Server        : bes2
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T3
  Server        : bes3
          Used(Full)       Used(      Full)        Sum
  Segment   0%(  0%)          0(         0)          0
  Page      0%(  0%)          0(         0)          0
 RD Area Name   : RD_T4
  Server        : bes4
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20

row_type'20'の挿入(2行目)

次のrow_type'20'の行は、RD_T3に挿入されました。

$ pdsql
COMMAND ?     +----2----+----3----+----4----+----5----+----6----+----7----+
INSERT INTO MATRIX_TEST VALUES (2,2,'20','ABCD');
KFPX27010-I            1 rows inserted
…
$ pddbst -t MATRIX_TEST
 RD Area Name   : RD_T1
  Server        : bes1
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T2
  Server        : bes2
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T3
  Server        : bes3
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20
 RD Area Name   : RD_T4
  Server        : bes4
          Used(Full)       Used(      Full)        Sum
  Segment 100%(  0%)          1(         0)          1
  Page      5%(  0%)          1(         0)         20