理論から学ぶデータベース実践入門を読んだメモ
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
- 作者: 奥野幹也
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (9件) を見る
読んだので気になった点をいくつかメモ。
全体としては、
RDBのもととなっているリレーショナルモデルの解説と、
それを軸にRDBでよく起きる問題に対する解説がされているようなイメージでした。
タイトル通り理論が中心で読み物っぽい印象。
肝心のリレーショナルモデルは書いてあることの意味はわかるんですが、
まだまだ実感をもってはら落ちするまでできなかったので、
いつかRDBで行き詰まった時に読み直してみたいです。
以下、気になった箇所メモ。
インデックス
- インデックスは左端から順にソートされる
- 左端の文字からindexを作成していく
- WHERE LIKE "a%" => index効く
- WHERE LIKE "%a%" => index効かない
- 複合インデックスの場合も左端から順にソートされるので、カラムの並び順が重要
パーティショニング
- 範囲やキーでパーティショニングを分割
- パーティショニングが適しているケース
- キーのカーディナリティが低い場合
- それ以外の場合はインデックスで十分な場合が多い
- 最新のデータへのアクセスが多いアプリの場合、日付でパーティショニングするのは有効。パーティショニングごとにindexが作成されるので
- インデックスはクエリが決まってから検討する
- 下記の場合は、インデックスを貼らずにテーブルスキャンをしたほうがよいケースがある
- 実行頻度が低い
- テーブルのサイズが小さい
- 検索結果が非常に多くの行にヒットする
インデックスの付け方
- where句から
SELECT * FROM t WHERE col1 > 100 AND col2 = 'abc';
(col1, col2)の複合インデックスより、(col2, col1)のほうが効率がいい
col1 > 100 は膨大な数ヒットする可能性がある
- join,サブクエリでもインデックスは有効なので、joinする条件サブクエリのWHERE句からインデックスを検討する
ソート
- WHERE col1 = 100 AND col2 = 200 ORDER BY col3
という条件なら、インデックス(col1, col2, col3)でインデックスだけで解決できる
インデックスはcol1 -> col2 -> col3の順でソートされ作成されているので、
WHERE col1 = 100 ORDER BY col3
になると遅くなる
ORに対するインデックス
- WHERE col1 = 100 OR col2 = 200
の時は(col1),(col2)の2つのインデックスが必要。インデックスマージされ検索される
インデックスはカラムの並び順が重要
- 同じカラムの組み合わせでも並び順が異なるインデックスを作る時がよい時もある
カーディナリティ
- WHERE句でcol1,col2,col3が条件となっていても、col1,col2でカーディナリティが高ければ、(col1, col2)だけのインデックスで十分なケースもある。
- インデックスが増えれば、更新時のオーバーヘッドが発生するため。
インデックスは
- どのカラムを含めるべきか、カラムのカーディナリティ、テーブルのサイズ、更新時のオーバーヘッド、クエリの実行頻度から総合して考える
やはりインデックスとかすぐに実践できる系のやつが気になっちゃます><
感謝致します。
PHPerが始めるgo言語入門 〜言語仕様〜
続いてgo言語の言語仕様を確認していきます。
五月雨でアレですが。
コメントアウト
1行 // 複数行 /* */
インポート
import ( "fmt" "strings" ) import ( f "fmt" //fという別名を使う _ "os" // _は対象パッケージを使わないことをコンパイラに明示する。使っていないパッケージがあるとコンパイルエラーになる . "strings" // .でパッケージ名を省略できる )
変数の宣言
var 変数名 型 = 値 var message string = "hellow world"
複数同時に宣言
var hoge, foo, bar string = "hoge", "foo", "bar" var ( a string = "a" b = "b" c = "c" ) 同じ型なら2つ目以降は省力可能
関数内部での変数宣言
:=で型推論で宣言できる func main() { // 同じ意味 // var message string = "hello world" message := "hello world" fmt.Println(message) }
定数
constで定数に const Message string = "hello world"
初期値なしで宣言
var i int // i = 0 int => 0 float => 0.0 bool => false string => "" 配列 => 要素0の配列 構造体 => プロパティが0の構造体 その他 nil
if文
if hoge > foo { } else if hoge < foo { } else { } 3項演算子はなし if1行だけもなし
ループ
ループはforだけ for i := 0; i < 10; i++ { } いわゆるwhile的なfor i := 0 for i < 10 { fmt.Printf("i = %d\n", i) i++ }
break,continue
i := 0 for { i++ if i > 10 { break //ループ抜ける } if i % 2 == 0 { continue //偶数なら次のループへ } fmt.Println(n) }
switch文
switch i { case 1: fmt.Println("1") case 2, 4: fmt.Println("2 or 4") case 5 < i: fmt.Println("greater 5") default fmt.Println("default") } switchで比較もオッケー phpだとcaseに入ってもbreakを書かないと次のcaseへ進むが、golangは1つcaseが実行されたら、switchを抜ける 逆に1つcaseを実行されても次のcaseに行きたい時は[fallthrough]と書く switch i { case 1: fmt.Println("1") fallthrough case 2, 4: fmt.Println("2 or 4") fallthrough default fmt.Println("default") }
関数
func 関数名(引数 型) 戻り値の型 { } func sum(i, j int) { //sum(i int, j int) fmt.Println(i + j) } func sum(i, j int) int { //sum(i int, j int) return i + j } func main() { n := sum(1, 2) fmt.Println(n) //3 } func change(i, j int) (int, int) { return j, i } func main() { x, y := 3, 4 x, y = change(x, y) fmt.Println(x, y) //4 3 }
名前付きの戻り値
func div(i, j int) (result int, err error) { if j == 0 { err = errors.New("divied by zero") return // return 0, errと同じ } result = i / j return // return result, nilと同じ }
無名関数
func main() { func(i, j int) { fmt.Println(i + j) }(2, 4) }
配列
goの配列は固定長 var arr1 [4]string //4つの要素がある配列 arr[0] = "a" arr[1] = "b" arr[2] = "c" arr[3] = "d" fmt.Println(arr[0]) // a // 宣言と同時に初期化 // どちらも同じ arr := [4]string{"a", "b", "c", "d"} arr := [...]string{"a", "b", "c", "d"} 関数に配列渡す時は値渡し
スライス
可変長の配列 var s []string s := []string{"a", "b", "c", "d"} fmt.Println(s[0]) // "a" 値追加 var s []string s = append(s, "a") // 追加した結果を返す s = append(s, "b") s = append(s, "c", "d") fmt.Println(s) // [a b c d] s1 := []string{"a", "b"} s2 := []string{"c", "d"} s1 = append(s1, s2...) // s1にs2を追加 fmt.Println(s1) // [a b c d]
range
先頭から順番に処理 いわゆるforeach的な感じ arr := [...]string{"a", "b", "c", "d"} for i, s := range arr { // i = 添字, s = 値 fmt.Println(i, s) }
値の切り出し
s := []int{0, 1, 2, 3, 4, 5} fmt.Println(s[2:4]) // [2 3] fmt.Println(s[0:len(s)]) // [0 1 2 3 4 5] fmt.Println(s[:3]) // [0 1 2 3] fmt.Println(s[3:]) // [3 4 5] fmt.Println(s[:]) // [0 1 2 3 4 5]
可変長引数
phpでもこういうのできるようになりますね 可変長で引数を取ることができる func sum(nums ...int) (result int) { // numsは[]int型 for _, n := range nums { //添字は捨てる result += n } return } func main() { fmt.Println(sum(1, 2, 3, 4)) // 10 }
マップ
ハッシュ的なやつです キーと値で、格納 var month map[int]string = map[int]string{} month[1] = "January" month[2] = "February" fmt.Println(month) // map[1:January 2:February] month := map[int]string{ 1: "January", 2: "February", } fmt.Println(month) // map[1:January 2:February] 値の取得 jan := month[1] fmt.Println(jan) // January 2つ目の戻り値に値があるかboolで返してくれる _, ok := month[1] if ok { // データがあった場合 } マップから情報を消すのはdelete delete(month, 1) fmt.Println(month) // map[2:February]
かなり雑でアレですが。。。
感謝致します。
PHPerが始めるgo言語入門 〜インストール〜
これまでperlちょぴり、ほぼphpでお仕事をしてきたのですが、
このままだともろもろ幅が広がらない危機感を感じていました。
とはいえ、C,javaとかやるのもなー
rubyやってもなー
な感じで行動に移していなかったのですが、
最近go言語が広まりつつあり、
静的型付け,コンパイルで処理が高速,並列処理が容易とのことで、
phpとは違う知識がつけれそう+おいおい仕事にもつながる可能性もありそうなので、
ちょっと本腰入れて取り組んでみようと思います。
なので、何はともあれインストールから。
Go言語のインストール - golang.jp
こちらを参考にインストール
- ソースをDL、解凍
- PATH設定
- インストール確認
ソースはこちらから
Downloads - The Go Programming Language
cd /usr/local wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz tar -xzf go1.4.2.linux-amd64.tar.gz vi /etc/profile export PATH=$PATH:/usr/local/go/bin
go version go version go1.4.2 linux/ad64
でインストール完了!
続いてhello world
hello.goを作成します。
vi hello.go package main import "fmt" func main() { fmt.Printf("hello, world\n") }
実行してみます
go runでコンパイルせずに実行できるそうです。
go run hello.go >hello, world
問題なさそうです。
今回は一旦ここまで。
次回からは、
- 言語仕様の確認
- 並列処理してみる
- WEBアプリつくってみる
とかとかやっていければと思います!
以上となります。
感謝致します。
Mackerelで3分で始める簡単サーバー監視~apache,mysql,redisとか監視~
前回に引き続きMackerel的なアレを。
Mackerelで3分で始める簡単サーバー監視 - 恥知らずのウェブエンジニア
今回は監視対象にapache,mysqlなどのミドルウェアの状況を監視対象にしてみます。
手順は簡単でメジャーなミドルウェアであれば、公式のプラグインがあるので、
それをインストールして、ちょっぴり設定を修正するだけです。
公式プラグインインストール
まるっとyumでインストール
yum install mackerel-agent-plugins
ソースもgithubで公開されています。
mackerelio/mackerel-agent-plugins · GitHub
apache
mackerel-agent-plugins/README.md at master · mackerelio/mackerel-agent-plugins · GitHub
公式の通りにserver-statusにアクセスできるようapacheのconfを修正します。
Listen 1080 ExtendedStatus On <VirtualHost 127.0.0.1:1080> <Location /server-status> SetHandler server-status </Location> </VirtualHost>
/etc/mackerel-agent/mackerel-agent.confに下記のように追記します。
/usr/local/bin/mackerel-plugin-apache2 -p 1080を直接実行することで結果等も確認できます
[plugin.metrics.apache2] command = "/usr/local/bin/mackerel-plugin-apache2 -p 1080" type = "metric"
mysql
mackerel-agent-plugins/mackerel-plugin-mysql at master · mackerelio/mackerel-agent-plugins · GitHub
デフォルトだとrootで実行されるので、専用のユーザを一応作りました。
GRANT ALL PRIVILEGES ON *.* TO mackerel@localhost IDENTIFIED BY '****' WITH GRANT OPTION GRANT ALL PRIVILEGES ON *.* TO mackerel@127.0.0.1 IDENTIFIED BY '****' WITH GRANT OPTION FLUSH PRIVILEGES
またまた/etc/mackerel-agent/mackerel-agent.confに下記のように追記します。
[plugin.metrics.mysql] command = "/usr/local/bin/mackerel-plugin-mysql -username=mackerel -password=****" type = "metric"
redisとか
同じ要領で/etc/mackerel-agent/mackerel-agent.confに下記追記しました。というかコメントアウトを解除。
# Plugin for Linux [plugin.metrics.linux] command = "/usr/local/bin/mackerel-plugin-linux" # Plugin for Redis # By default, the plugin accesses Redis on localhost. # Currently AUTH password has not been supported yet. [plugin.metrics.redis] command = "/usr/local/bin/mackerel-plugin-redis"
でこれらが終わったらmackerel-agentを再起動。
sudo /etc/init.d/mackerel-agent restart
もし失敗した際は、/var/log/mackerel-agent.logを確認してください。
またApikeyがconfの下に書いてある場合は、上部に持ってくる必要があるみたいです。
これだけでリソースなど下記のようにグラフ化されます。
開発サーバーなので、動きがなくてアレですがちゃんとモニタリングできているようです。
なんて簡単・・・
ありがたいです。
感謝致します。
Mackerelで3分で始める簡単サーバー監視
会社などでは、サーバーの監視でzabbixやnagios、muninなどが使われているかと思いますが、
個人や小さいプロジェクトでは特にサーバー監視などしてないことも多いのはないでしょうか。
自分も個人のはサーバー監視していない状態でした。
特に必要が出たわけでもないのですが、Mackerelで簡単に監視できるそうなのでやってみました。
Mackerel(マカレル)とは
サーバーの監視やアラート、グラフ化をしてくれるサービスです
Mackerel: 新しいアプリケーションパフォーマンスマネジメント
手順
- Mackerel登録
- mackerel-agentをインストール
- サービスとかロールを設定
Mackerel登録
何はともあれ登録します。
普通に登録するだけです。
Mackerel: 新しいアプリケーションパフォーマンスマネジメント
mackerel-agentをインストール
監視対象のサーバーにmackerel-agentをインストールします。
mackerel-agentが定期的に諸々の情報をMackerelに送るようです。
スタートガイドのままです。
//リポジトル追加 curl -fsSL https://mackerel.io/assets/files/scripts/setup-yum.sh | sh //yumでインストール sudo yum install -y mackerel-agent //設定ファイルにapikey追記 sudo sh << SCRIPT cat >>/etc/mackerel-agent/mackerel-agent.conf <<'EOF'; apikey = "***********************" EOF SCRIPT //agent起動 sudo /etc/init.d/mackerel-agent start
サービスとかロールを設定
サービスはそのままサービスやプロダクト単位のもを設定
ロールはwebとかdbなどサーバー単位の役割を登録します
そしてそれらをサーバーに紐付けます。
これだけで完了・・・
これだけで↑的な基本的なサーバーリソースの監視とアラートの設定等ができます。
会社的にやるとなるとセキュリティ的なアレですんなり行かないかもしれないですが、
個人の場合はありがたく使わせて頂きたいですね!
通知もメールやhipchat,slackにも送れるとのこと。
またプラグインを入れることでapacheやmysqlの監視もできる模様。
データをAPIに送ることで任意のデータの監視等も可能だそうです。
監視といえばコレ
Denki Groove - Nothing Gonna Change [Berlin ...
感謝致します。
jenkinsでLDAP認証とジョブごとの権限設定
jenkinsは便利ですが、最初の「とりあえずやってみようぜ」的な流れのまま、
そこそこ危険なジョブも誰でも実行できたりと権限周りがアレな状態なので整理してみました。
なので、認証はLDAPを使い、LDAPのグループで大まかな権限設定行い、
細かいのはジョブごとに権限設定してみました。
バージョン
Jenkins 1.598
LDAP Plugin 1.11
LDAP認証設定
普通にGUIから設定
設定項目 | 内容 | 例 |
サーバー | LDAPサーバー(必要あればポートも) | 10.9.**.*** |
root DN | 検索するroot | dc=hoge_ldap |
Group search base | 検索対象のグループ | ou=hoge_Group |
Group search filter | 検索グループフィルター | cn=*_hoge |
※最初は権限管理を「全員に許可」にしておいてから、LDAPログインできるか確認する。
もし設定に不備があると、ログインできなくなる可能性があります。
その場合、/var/lib/jenkins/config.xmlを直接修正する必要があります。
グループごとの権限設定
グループごとの権限設定は、Jenkins -> Jenkinsの管理 -> グローバルセキュリティの設定から行います
- 権限管理 -> 行列による権限設定(プロジェクト単位)にチェックを入れる
- 対象のグループごとに権限を設定(ここの設定でおおまかな設定を行い、後述のジョブごとの設定で細かい設定を行う)
ジョブごとの権限設定
- 各ジョブの設定 -> 権限設定(プロジェクト単位)の有効化をチェックする
- ここでジョブごとにグループの権限を設定します。
これで取り急ぎ、誰でも何でもできるとかjenkinsだけユーザ作るとかは必要なくなりそうです。
感謝致します。
logmonでログをリアルタイム監視
サービスを運用しているとどうしても不具合が出てしまいます。
出た不具合はできるだけ早く察知したいです。
ということでlogmonを使ってログをリアルタイムに監視して、
致命的なエラーが出たら、メールなりチャットなりで通知するようにしてみました。
インストール
wget http://www-06.ibm.com/jp/linux/tech/doc/attachments/00057580_logmon_20100411.tgz tar zxvf 00057580_logmon_20100411.tgz cd logmon_20100411/ sh setup.sh
設定ファイル作成
今回はとりまapacheのerror_logにFatal errorが出たら、通知します。
vi /etc/logmon/logmon.conf #監視対象ログファイル :/var/log/httpd/error_log #検索文字列 (.*Fatal.*) #検索後の実行コメンド <%%%%>は検索した行 php ~/send_mail.php "<%%%%>"
起動
/etc/init.d/logmon start #設定変更後は /etc/init.d/logmon restart
なんて簡単!
感謝致します。