PSI Labs RSS feed

vim に Go言語のシンタックスハイライトを追加する

こんにちは、tomita です。

Google が開発している Go言語 を少し触っています。新しい言語に触れるといろいろと勉強になりますね…。

さて、現在は CentOS 上の vim でコードを書いているのですが、シンタックスハイライトがされないため見ずらいです。

vimgo1.png

「go vim syntax」で調べると、シンタックスハイライト+補完+自動ビルド…といった「全部盛り」がヒットするのですが、今回は *.go ファイルを開いたときにシンタックスハイライトされる設定のみを行います。

シンタックスハイライトファイルを作成する

まず、ホームディレクトリに .vim/syntax ディレクトリを作成します。
その後、.vim/syntax 以下にシンタックスハイライト用ファイル go.vim を作成します。Go言語用のシンタックスハイライト用ファイルは https://github.com/fatih/vim-go/blob/master/syntax/go.vim を使わせて頂きます。

mkdir -p ~/.vim/syntax
cd ~/.vim/syntax
wget https://raw.githubusercontent.com/fatih/vim-go/master/syntax/go.vim

ファイルタイプが認識されるようにする

次に *.go ファイルを開いたときに自動認識されるよう、.vim ディレクトリ以下に以下内容で filetype.vim を作成します。

if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.go   setfiletype go
augroup END

ファイルツリーはこんな具合です。

.vim
|-- filetype.vim
`-- syntax
    `-- go.vim

これで vim で *.go ファイルを開くと以下のようにハイライトされます。

vimgo2.png

go言語に限らず、上記方法を使えば手軽にシンタックスハイライトを追加できそうですね。以下が参考になります。

それでは~


Oracle DBでの大量データ(数億レコード)のUPDATEの手法

こんにちは。shintaniです。

今回は超大量データを一括UPDATEする場合の手法を紹介します。


テーブル内の全データをUPDATEする場合、単純に書くと下記のようなSQLとなります。

UPDATE  TBL_TEST_TABLE
  SET
     COL1 = '01234567890123456789'

レコード数が少なければこのSQLで問題ありません。

しかし、数億レコードのような大量のレコードが入っている場合は上手くいきません。
長時間掛かった挙句、UNDO表領域を使い果たして
「ORA-30036: (UNDO表領域'UNDOTBS'内)でセグメントを拡張できません」
というエラーが返ってくることがあります。

この場合、WHERE句でレコードを絞り込みつつ何度もUPDATEしていると思います。
しかし、WHERE条件で上手く絞り込みするのが難しい場合も多々あります。
(条件が細かすぎる場合は何百回もUPDATEを実行することになって検索の時間が無視できなかったり、
 大まかすぎると前述のエラーが起こったりします)

この場合は下記のようなPL/SQLにすると、汎用的に色々なテーブルで使いまわせ、
かつ実行時間も短くて済みます。

DECLARE
    CURSOR c1 IS SELECT rowid c_rowid FROM TBL_TEST_TABLE;   -- ***
    v_rowid dbms_sql.urowid_table;
    v_update_count  NUMBER(20) := 0;
BEGIN
    OPEN c1;
        LOOP
            FETCH c1 BULK COLLECT INTO v_rowid LIMIT 10000;    -- 1万レコード単位でコミット
            EXIT WHEN v_rowid.count = 0;

            FORALL i IN 1..v_rowid.count
                UPDATE TBL_TEST_TABLE   -- ***
                  SET
                     COL1 = '01234567890123456789'    -- ***
                    WHERE rowid = v_rowid(i);

            v_update_count := v_update_count + SQL%ROWCOUNT;
            COMMIT;
        END LOOP;
    CLOSE c1;

    DBMS_OUTPUT.PUT_LINE('UPATE件数 = ' || v_update_count);
END;
/

全体としては大きくなりましたが、個々のSQLで修正する箇所は *** を付けた箇所のみです。後はそのまま使えます。

このPL/SQLはBULK COLLECTという手法を使っています。
rowid で1レコードずつUPDATEするより、こちらの方が遥かに早いです。


単純なUPDATEと、上記のBULK COLLECTの手法の処理時間を比較してみました。

【DB全体の設定】
・UNDO表領域 15G。 自動拡張OFF
・sga_max_size - 8G

【テーブルの設定】
・約50列。
・2列に対して更新。
・インデックスは主キー1つのみ(UPDATEの対象列ではない。もし対象の場合はインデックスを一時的に無効化しないとトンデモない時間が掛かります。)


・100万レコード
 (テーブルのセグメントサイズ:350M)

単純UPDATE - 10秒
BULK COLLECT - 10秒


1000万レコード
 (テーブルのセグメントサイズ:3.5G)

単純UPDATE - 10分52秒
BULK COLLECT - 13分10秒


2000万レコード
 (テーブルのセグメントサイズ:6.8G)

単純UPDATE - 37分40秒
BULK COLLECT - 35分 7秒


1億レコード
 (テーブルのセグメントサイズ:34G)

単純UPDATE - 2時間半後にORA-30036エラー
BULK COLLECT - 3時間29分


レコード数と時間が単純な比例となっていないのは、SGAにデータバッファを溜めておける量が影響していると思われます。

最後の1億レコードでは、単純UPDATEではエラーが起こってしまいましたが、
BULK COLLECT ならばエラーがも起こらず、かつ単純UPDATEが成功する場合と遜色無い時間で完了しました。

このような超大量データのUPDATEで苦労されている方は、どうぞお試し下さい。

ではでは。





[設計]SQL設計書の書き方(続き)

こんにちは。shintaniです。

前回のSQL設計書(データ取得図)の記事 の続きです。

今回はGROUP BYやソート順の書き方、そしてインラインビューを使う場合と、書くときのポイントを説明します。




まずはGROUP BY とソート順。
(前回の紹介では書き忘れていました・・・)

SQL設計書01.JPG




ソート順とグループ化項目の位置に違和感を覚える方もいるでしょう。
しかしソート順は図に書いた理由の他にも「SELECT項目がどう並ぶか?」という観点から、SELECT句のそばにあった方が分かりやすいです。
そしてグループ化項目は「テーブル結合後にどう集約するか?」なので、図の下にあった方が分かりやすいです。



次は インラインビュー。



SQL設計書02.JPG


こんな感じになります。
(インラインビューにしなくても出来る・・・というのは御容赦を)




書くときのポイントですが、


SELECT句はこだわらない。テーブル結合にこだわる

です。

SELECT句の部分が間違っていても後で修正は容易です。
リターンされるレコード数が増えるわけでもなく、かつ影響範囲はその列だけだからです。
(インラインビューのSELECT句だったら困るかもしれませんが・・・)
半面、使用するテーブルや結合条件に誤りがあった場合、影響は甚大です。

また、分析関数を使ったりCASE式での複雑な分岐があったりする場合、そこに大量に記述して「テーブル結合」が見辛くなってしまうことがあります。
その場合にはいっそ「列A:別紙_列Aの取得方法、を参照」などと書いて、別シートに移してしまった方が分かりやすいです。

ではでは。






[設計]SQL設計書の書き方

お久しぶりです。shintaniです。

今回はSQLの設計書について書いてみます。
とはいっても「正しいSQLの設計書」などとおこがましいことを言うつもりはありません。
「今までより多少マシなSQLの設計書」という程度に捉えて下さい。

このような帳票があるとします。
WS000000.JPG

これに対して、下記のような詳細設計書(SQL設計書)を書いているプロジェクトが結構あるかと思います
WS000001.JPG

これでは殆どSQL自体を書いているのと変わりません。
テーブル同士の繋がりや絞り込み条件も分かり辛いです。

これに対し、下記は私が以前関わったプロジェクトで作ったSQL設計書です。
(そこでは ”データ取得図” と呼んでいました)
WS000005.JPG

これはE-R図とは異なるものです。
あくまでSQLの結合方法や条件設定などを記述したものです。
この形式のSQL設計書には以下のようなメリットがあります。

---------------------------------------------------------------------------------------

1 図として記述することで書いた当人も理解が深まる
2 テーブル結合、条件などが一目で分かる。結合条件の記述漏れもすぐに分かる。
3 画面、帳票は「ヘッダ」と「データ」部分に分かれることが多いが、それらが1対nで結ばれているかどうか分かる。
4 この形式ならばお客さんもデータ取得の方法が分かりやすい。
  「画面のデータがおかしい」という不具合が出た際、これを見せてすぐに正しいデータの取得方法が分かったことも多い。

---------------------------------------------------------------------------------------

「副問い合わせやUNION ALLとか色々あるだろう!その場合はどうするんだ!?」
という意見もあると思いますが、例えばunion allは下記のように書きました。

【UNION ALLの場合】
WS000006.JPG

ただ分析関数など図オンリーでは対応仕切れないものもあり、
その場合はテーブル結合条件だけ書いてその他は文章で記述しました。

様々なSQLについてこの形式で記述しましたが、殆どの場合で
「仕様書を記述する手間 < 実際にSQLを作成する手間」
が成り立ち、別の人がこれを元に実際のSQLを作成することが出来ました。

今も試行錯誤している途中ですが、それなりに使える設計書ではないかと思います。
参考にして頂ければ幸いです。

ではでは。



【2017/04/23 追記】

GROUP句やソート条件などの書き方について、続きの記事を書きました。
[設計]SQL設計書の書き方(続き)

よろしければこちらもご覧下さい。



PHP7.1.0からセッション設定が簡単になりました

こんにちは、tomitaです。

昨年12月に PHP-7.1.0 がリリースされました。

機能もいろいろ追加されましたが、セッション生成方法も変更され、php.ini の session 設定項目も変わりました。

削除されたsession設定項目

  • session.entropy_length
  • session.entropy_file
  • session.hash_function
  • session.hash_bits_per_character

追加されたsession設定項目

  • session.sid_length
  • session.sid_bits_per_character

session.sid_length はセッションID文字列の長さを指定します。最低32を指定しろ、とマニュアルにはあります。

session.sid_bits_per_character はセッションID文字のビット数(4,5,6 のいずれか)を指定します。マニュアルには 5(0-9、a-z)を奨励とあります。

例えば

session.sid_length = 32
session.sid_bits_per_character = 5

を設定した場合、生成されるセッションIDは以下のようになります。

bq1j0rij95ud8gi52caqvc3bcga4i5tf

以前よりも設定項目が減り、2項目を指定するだけで堅牢なセッションIDが生成できます。できればもう少しはやく実装してほしかった…

それでは~