技術関連の覚書

案件でやったり自宅で試したことの覚書

SQLのパフォーマンスを最適化するために(2)

つづきです

前回分はこちらになります SQLのパフォーマンスを最適化するために - 技術関連の覚書

インデックスを使えなくする検索条件

インデックスを作っても使えなくなる事があるので気をつけて避けるようにしましょう 得に何も書かない場合はITEM1をインデックス項目とします

複合検索条件をORで結ぶ

SELECT
  ITEM1
FROM
  TABLE1
WHERE
  (ITEM1=? AND ITEM2='000') OR (ITEM1=? AND ITEM2='111')

この場合、UNIONやUNION ALLにする方がよいようです

SELECT
  ITEM1
FROM
  TABLE1
WHERE
  ITEM1=? AND ITEM2='000'
UNION
SELECT
  ITEM1
FROM
  TABLE1
WHERE

ITEM1=? AND ITEM2='111'

違う項目をORで結ぶ

SELECT
  ITEM1
FROM
  TABLE1
WHERE
  (ITEM1=? OR ITEM2='000') AND ITEM3=?

この場合は (ITEM1=? AND ITEM3=?) OR (ITEM2=‘000’ AND ITEM3=?) に分解できます

インデックス項目に対するOR

SELECT
  ITEM1
FROM
  TABLE1
WHERE
  (ITEM1='000' OR ITEM1='001' OR ITEM1='002') AND ITEM3=?

同一項目をOR検索する場合はINに置き換えられるのでINを使う

ITEM1 IN ('000', '001', '002')

INを使った副問合せ

SELECT
  ITEM1
FROM
  TABLE1
WHERE
  ITEM1 IN (SELECT ITEM1 FROM TABLE2 WHERE ITEM1>'002')

これはFROM句でJOINさせた方がいいようです

SELECT
  ITEM1
FROM
  TABLE1 T1
INNER JOIN TABLE2 T2 ON
  T1.ITEM1 = T2.ITEM2
WHERE
  T2.ITEM1>'002'

SQL関数を使う

関数を使うとインデックスが適用できなくなるので代用できる物があれば避ける 例) LEFT関数で前方一致をLIKEでの前方一致にする ITEM1=LEFT()   ↓ LIKE 'X%'

項目同士で文字列結合したものとの比較

ITEM1 || ITEM2='AAA000'      ↓ ANDで結合しましょう

インデックスを使う優先順位

ランキングは以下のとおりです

  1. =で比較するPK

  2. =で比較するインデックス

  3. LIKEでの前方一致

  4. INでの比較

  5. BETWEENでの範囲検索*1

  6. 不等号(>,>=,<,<=)での比較

  7. GROUP BYかORDER BYの列にあるインデックス

副問合せの検索方法

何となく、結合と似たところがあります 副問合せは作業表を作るのでこれがパフォーマンスを低下させる原因になる場合があります

NESTED LOOPS WORKTABLE SUBQ

外のSQLから1件検索ごとに副問合せのSQLを検索してワークテーブルを作ります

WORKTABLE ATS SUBQ

インデックスを使って副問合せを検索する方法です

WORKTABLE SUBQ

副問合せの選択式の値を求めて作業表を作って、外を実行して1件検索して副問合せの結果を問い合わせます

HASH SUBQ

あらかじめ副問合せ結果からハッシュ表を作成しておいて,外側の問合せを1行取り出すごとに外側の問合せの値をハッシングして,ハッシュ表と突き合わせをする方式です。

NESTED LOOPS ROW VALUE

副問合せのインデクスを使用して,外側の問合せの結果との条件を評価します

3つ(だけ?)くらい中途半端な状態ですが、出かける時間がきてしまうので続きはWEBで(ここだろと言うツッコミ)

*1:A >= x AND A <= y と言う検索の場合はBETWEENに内部的に展開されます

systemd-tty-ask-password-agent

SQLの続き各予定でしたが、PC立ち上げたときにふと気がついたので

httpsをサービス起動するときに手動起動した場合はそのままパスフレーズを入れればいいけど 自動起動した場合、バックグラウンドで起動した場合はパスフレーズが入れられないので下記のコマンドを使います

systemd-tty-ask-password-agent --query

これを以前調べたときにsshでログインしてからと書いてあったので、素直にssh経由でやってたのですが このままコマンド打ったらどうなるかとふと思ったので打ってみたらそのままパスフレーズ入力が出てきたのでわざわざターミナルを立ち上げる必要は無かったということでした

f:id:boctok-ctpoba:20170401121857p:plain

SQLのパフォーマンスを最適化するために

ひとまず棚卸が終わったので、今回からちゃんと書いていきます。

これまで書いてあった物を見てDBのメモはあったけどSQLについて書いて無かったので今回はSQLについて書いていきます(ちょうど今やってることだし)。

SQLと言うのはいろいろな現場に行くごとに用語が違っていたりしてどれが標準的な言葉かわからない事もあるので、 まず言葉の定義からしておきます。

用語 意味 他の言い方
副問合せ SQLのFROM句やWHERE句で別のSQLを定義すること
副問合せの検索結果をWHERE条件にしたり、テーブルと同様に扱うことができる
サブクエリー
別名 テーブルや項目に対してつける別の名前
関数を使った場合にもつけることができ、選択式、テーブル名につけることができる
エイリアス
外表 テーブル結合時に基準になる側のテーブル
下記のSQLのTABLE1に該当するが、結合結果も次に結合がある場合はそれが外表として扱われるためTABLE1とTABLE2の結合結果もTABLE3に対する外表となる
外部表、駆動表
内表 テーブル結合時に外表から結合される側のテーブル
下のSQLではTABLE1に対するTABLE2、TABLE1とTABLE2の結合表に対するTABLE3
アクセスパス SQL実行時にどのような手順で実行していくかを示したもの 実行計画
SELECT
  COUNT(ITEM1) CNT, ITEM1 I1, ITEM2 I2
FROM
  TABLE1 T1
INNER JOIN TABLE2 T2 ON
  T1.ITEM1 = T2.ITEM1
INNER JOIN TABLE3 T3 ON
  T2.ITEM3 = T3.ITEM3
WHERE
  T1.ITEM2 = ? AND
  T2.ITEM1 IN (
    SELECT
      ITEM1
    FROM
      TABLE1
   ) SUB_T1
ORDER BY
  ITEM1
GROUP BY
  ITEM1, ITEM2
;

インデックスの使用

SQLのパフォーマンスをあげるための一つとしてインデックスを使用する方法があります。 インデックスとは、本の索引と同じく、頭文字などを見出しにしてそれがどこにあるかを記述しているところです。

f:id:boctok-ctpoba:20170331235955p:plain

インデックスを使うと、検索する量を減らせるため速度をあげることができます。

テーブルの結合順

テーブルの結合順や結合項目によってパフォーマンスが変わります。 結合の方法としては以下の物があります

  • NESTED LOOPS JOIN

  • SORT MERGE JOIN

  • HASH JOIN

  • CROSS JOIN

NESTED LOOPS JOIN

外表からインデックスを利用して内表を検索する結合方法なので、結合条件にインデックスが使われていることが必要 外表の件数を少なくすることで検索回数を減らすことができるので、件数の少ないテーブル、検索条件によって件数が絞り込まれるテーブルを外表にする

計算量:O(N \log{M}) *1

SORT MERGE JOIN

外表、内表をソートして上から順に検索して結合していく方法 外表が大量データの場合はNESTED MERGE JOINよりも有利な場合がある

計算量:O(N+M)

HASH JOIN

データベースで、2つの表の小さい方を使用して、メモリー内にハッシュ表を作成する結合 大きい方の表をスキャンしてハッシュ表を調べ、小さい方の表の対応する行のアドレスを見つけます メモリー内にハッシュ表を作るため大量のメモリが必要になるが、メモリが多い場合は有利な検索方法

計算量:O(N h_c + M h_m + J) *2

CROSS JOIN

外表から1レコードずつ内表を全件検索する方法 外表件数×内表件数だけの検索回数があるためパフォーマンスはもっとも悪い

計算量:O(NM)

計算量についてはここを参照しました www.madeiradata.com

今日はここまで 意外に時間がかかりました(数式の書き方調べたり色々と)

さーて、明日のこのブログは

インデックスを使えなくする検索条件

インデックスを使う優先順位

副問合せの検索方法

の3本です 来週もまた見てくださいね

と言いながら、明日は出かけるのでかけるかどうかわかりません

(某国民的アニメとは関係ありません)

*1:Oは計算量を表す記号、括弧内に入る数に応じて変化する量。N,Mは外表、内表のそれぞれの件数

*2:件数はN<M、hc:ハッシュテーブルを作る計算量、hm:ハッシュマッチングの計算量、J:Jorker=ハッシュ関数の動的な計算量

Linuxでのファイル復旧

このツールを使います DiskDiggerdiskdigger.org

なぜか拡張子がexe

$ sudo apt-get install libmono-system-windows-forms4*

Download DiskDigger, unzip it, and launch it with sudo:

$ wget http://diskdigger.org/diskdigger_linux.zip
$ unzip diskdigger_linux.zip
$ sudo mono DiskDigger.exe

If the above line gives an error, try explicitly specifying the runtime version:

$ sudo mono --runtime=v4.0 DiskDigger.exe

Elasticsearch

※この情報は古いのであまりあてになりません。現時点の最新版は5.3.0です。

インストール前提

jdk1.7以上をインストール済みであること rootユーザで実行する

インストール

yumを使ってインストールするためにアクセスキーをインポートする

rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

/etc/yum.repos.d/elasticasearch.repo を作成する

[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=https://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=https://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

yumでインストール

yum -y install elasticsearch

サービスを登録

systemctl daemon-reload
systemctl enable elasticseach
systemctl start elasticsearch

起動確認 サーバ上で

# curl http://localhost:9200
{
  "name" : "Him",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.3.3",
    "build_hash" : "218bdf10790eef486ff2c41a3df5cfa32dadcfde",
    "build_timestamp" : "2016-05-17T15:40:04Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0" 
  },
  "tagline" : "You Know, for Search" 
}

プラグインの導入

プラグインを導入するためのコマンドは Elasticsearchインストールディレクトリ /bin/plugin パスを通すかフルパス指定で実行してインストール plugin install インストールプラグイン名 入れておきたいプラグイン

プラグイン インストール文字列 用途
Marvel Documentation elasticsearch/marvel/latest 管理、モニタ用
Kuromoji /elasticsearch/elasticsearch-analysis-kuromoji/2.0.0 日本語解析
CSV River Plugin river-csv -url https://github.com/AgileWorksOrg/elasticsearch-river-csv/releases/download/2.0.1/elasticsearch-river-csv-2.0.1.zip CSVデータインポート

Couchbase

インストール

公式サイト からインストールファイルをダウンロードする。

インストーラを実行するとそのままサーバの起動までスタートします。

http://インストールサーバ:8091 へアクセスすると設定画面が開きます。

Apache Solr

概要

インストール

  1. apache solrのページからダウンロード

  2. ダウンロードファイルを解凍する

  3. 解凍したディレクトリへ移りbin/solr -p ポート番号 で起動する

$ wget http://ftp.tsukuba.wide.ad.jp/software/apache//lucene/solr/5.3.0/solr-5.5.0.tgz
$ tar -zxvf solr-5.5.0.tgz
$ cd solr-5.5.0
$ bin/solr -p 接続ポート