mysqlについて、機能とかInnoDBとか文字コード等々

個人的にDBの中ではMySQLを使うことが多いです。しかしDB自体初めから組む機会は少ないので、良く調べてしまう事をメモします。

InnoDBとMyISAMはどっちを使う?

「とりあえずInnoDB」位の認識ですが、MySQL5.5からInnoDBがデフォルトになったみたいです。特別な理由がなければ、InnoDBで問題がないと思います

InnoDBを選び忘れて、MyISAMのままだったと言うことが無くなって、うれしいです。

InnoDBって?

・トランザクション処理ができる
・行ロック方式なのおすすめ(MyISAMはテーブルロック方式)
・チューニングは、innodb_buffer_pool_size, key_buffer_size
・バックアップしやすい

MySQL 5.6新機能

・マルチスレッド・スレーブ対応
・InnoDBで全文検索ができる
・InnoDBでNoSQLアクセスで、高速なキー・バリュー操作や、ビッグ・データ環境でのデータの高速取得が可能

その他詳細は MySQL Database 5.6の特長

文字コードは?

文字コードは「utf8mb4」
MySQLには、「utf8」と「utf8mb4」があります。MySQL 5.5.3以降ならば、utf8mb4を選択すればいいでしょう。

特徴
・utf8 → 4バイト文字列が入った場合文字化けする。
・utf8mb4 → UTF8で4バイト文字を扱える

接続照合順序

「general_ci」か、「unicode_ci」を選べばOKなようです。この2つは、文字列検索時に挙動が違います。それぞれの特徴です。

特徴
「general_ci」
・大文字小文字もマッチする。「A」で検索すると、「A,a」ともにマッチする。
・unicode_ciに比べて、文字検索が速い。

「unicode_ci」
・大文字小文字もマッチする。「A」で検索すると、「A,a」ともにマッチする。(general_ciと同じ)
・半角全角もマッチする。「A」で検索すると、「A,a,A,a」にマッチする。
・平仮名、カタカナ、濁音などもマッチする。「さ」で検索すると、「さ, ざ, サ, サ」などにもマッチする。
・general_ciに比べて、文字検索が遅い。

検索結果(select)で、無駄なマッチがない「general_ci」を選ぶ方が多いそうですが、「ドラえもん」を検索したとき、「どらえもん」 ,「ドラエモン」 ,「ドラエモン」 , 「どらエモン」にもヒットさせたいときは、「unicode_ci」を選ぶとOKです。
個人的には、「unicode_ci」をよく使います。

数値型属性のUNSIGNEDとZEROFILL

・UNSIGNED
 負の数は使えなくなるが、正の数は2倍の範囲まで使える。
 浮動小数点型(float, double)型は負の値が無くなるのみ

・ZEROFILL
 ZEROFILLを付けた場合、自動的にUNSIGNE属性になる。
 指定した桁数になるまで、0が埋まる
 例)int(4) UNSIGNED ZEROFILL で、数値12を入れると、0012になる。

データ型

データ型は様々あります。個人的に、おおむね選ぶときの基準です

数値 :int型
文字列:100文字以内なら、char(100)型、超えるなら、txet型
小数点:decimal(M,D) M:桁数,D:小数点
日時 :datetime (timestampは、2038-01-19 03:14:07秒まで)
データ型については、別記しています。

クエリの基本

SELECT * FROM table_name WHERE 条件;

DELETE FROM table_name WHERE 条件;

INSERT INTO table_name ( key1, key2, …) VALUES ( value1, value2, …);

UPDATE table_name SET key1 = value1 [, key2 = value2, …] WHERE 条件;

mysqlのcollateを使って大文字-小文字や全角-半角を無視した検索 – end0tknrのkipple – web写経開発

MySQL5.5、utf8mb4 の使用について – PHPプロ!Q&A掲示板

運用視点なMyISAMとInnoDBと。 | LexTech

MySQL :: MySQL Database 5.6

chromeで、Content-Type の調べ方

『Content-Type』を調べたい事がありましたので、調べ方をメモしておきます。

chromeで、Content-Type の調べ方

Content-Type について

その前に、『Content-Type』について復習です。

たとえば、インターネットでファイルのダウンロードを行う時等、ファイルに拡張子がなかったり、拡張子からファイルの種類が分からない場合がある。
その場合、「これから返すファイルの種類」をContent-Typeによって示すことで、ファイルの種類を受け取る側が知ることができる。またその種類に応じて、Webブラウザがそのまま表示したり、ファイルとして保存したり、他のアプリケーションを起動してそれを用いて出力したり、と処理を変更する。

Content-Typeとは : JavaA2Z

簡単に言うと、windowsでの拡張子に当たる部分です。
例えば、ブラウザでweb上の『.cgi』ファイルにアクセスした場合、拡張子からCGIだとわかっても、帰ってくるデータが、テキストなのか、画像なのか、scriptなのか、ダウンロードファイルなのか、ブラウザは分からは判断できません。したがって、『Content-Type』にファイル形式を明示するのです。

今までコードのお約束事として記述していた下記のような『Content-Type』は、「htmlファイルです」と、ブラウザに伝えていたのです。(HTML5からは記述しなくても、”text/html”として扱われるようです。)

# HTML
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
# php
header("Content-type: text/html; charset=utf-8");

Content-Type を調べてみる。

本題です。実際にheader情報の『Content-Type』をchromeを使って確認してみます。
chormeのアドレスバーに

chrome://net-internals/#events

を、入力します。(chrome://about/ と入力すると、開発者向けの機能が提供されています。その中の1つです。)

chrome_net-internals01

表示されたリストから、確認したい通信をクリックします。
当サイトだと、
Source Type : URL_REQUEST
Description : http://blog.cototoco.net/
です。ウィンドウ右側に詳細が表示されます。

詳細の中、さらに、HTTP_TRANSACTION_READ_RESPONSE_HEADERS、に『Content-Type』が記載されています。

chrome_net-internals02

当サイトの『Content-Type』が
Content-Type: text/html; charset=UTF-8
だとわかります。

実験

html5に『Content-Type』(metaタグ)有り無しで実験してみます。ちなみに、HTML5では省略しても”text/html”と扱われるので、省略しています。

# meta 有り無し
<meta http-equiv="content-type" content="text/html" charset="UTF-8">

html5に『Content-Type』有りの場合

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html" charset="UTF-8">
<title>Content-Typeサンプル</title>
</head>
<body>
<p>HTML5 Content-Type はどうなっているか?</p>
</body>
</html>

html5に『Content-Type』有りの場合の『Content-Type』は
Content-Type: text/html となっていることが確認できました。

# meta 有りのheader情報
HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 200 OK
  Date: Fri, 11 Jul 2014 05:27:51 GMT
  Server: Apache
  Last-Modified: Fri, 11 Jul 2014 05:27:41 GMT
  ETag: "5e1f2e-e8-53bf75cd"
  Accept-Ranges: bytes
  Content-Length: 232
  Connection: close
  Content-Type: text/html

html5に『Content-Type』無しの場合

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Content-Typeサンプル</title>
</head>
<body>
<p>HTML5 Content-Type はどうなっているか?</p>
</body>
</html>

html5に『Content-Type』有りの場合の『Content-Type』は
明記されていないようです。(注:キャッシュが残っている場合はキャッシュが表示されているようです。)

# meta 無しのheader情報
HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 304 Not Modified
   Date: Fri, 11 Jul 2014 05:38:35 GMT
   Server: Apache
   Connection: close
   ETag: "5e1f2e-a2-53bf782f"

以上、chromeで、Content-Type の調べ方です。
また、この方法で、header情報も同時に確認できることになります。

Content-Typeとは : JavaA2Z

gihyo.jp

ディープコピー 【Ruby】

『オブジェクトのコピー』,『メソッドの引数(値渡し、参照渡し)』の延長です。私もよくわかっていないので、さらっと流します。

配列のコピーや、メソッドの引数に配列を渡すとき、『副作用』(コピー先の値を変更すると、コピー元の値も変更される)が発生するので、『副作用』を避ける場合、cloneメソッドで複製を作る方法を紹介しました。

しかし、多重ループの場合 cloneメソッドでは、2次以上の部分に副作用が残ります。その際に用いるのが、ディープコピー(deep copy)という方法です。

Javaではキチンと?書かないといけないようですが、rubyでは次のコードでディープコピー行えるようです。(*2)

obj_m = Marshal.load(Marshal.dump(obj))

Marshalモジュール : オブジェクトをファイル(または文字列)に書き出したり、読み戻したり する機能を提供するモジュール(*1)
渡したオブジェクトを、Marshal.dump で出力し、Marshal.loadで読み込み、オブジェクトを返すイメージです。

実際にサンプル(sample01)を見てみます、まず clone メソッドでコピーした場合の副作用を見てみます。
4, 5行目 : clone で複製したオブジェクトは別物になっています。
しかし、
6, 7行目 : arrA[0]と、arrB[0]は同じオブジェクトを参照
8, 9行目 : arrA[1]と、arrB[1]は同じオブジェクトを参照
しているので、arrA[0][1]の値を変更した際に、arrBの中の値も変更されています(副作用)。

arrA = Array.new(2){ |i| Array.new(4){ |j| i * 4 + j + 1 } }
p arrA # => [[1, 2, 3, 4], [5, 6, 7, 8]]
arrB = arrA.clone
p arrA.object_id # => 17481360
p arrB.object_id # => 17481200
p arrA[0].object_id # => 17481350
p arrB[0].object_id # => 17481350
p arrA[1].object_id # => 17481340
p arrB[1].object_id # => 17481340
arrA[0][1] = 10
p arrA # => [[1, 10, 3, 4], [5, 6, 7, 8]]
p arrB # => [[1, 10, 3, 4], [5, 6, 7, 8]]

ディープコピーを使ったサンプル(sample02)では、
6, 7, 8, 9行目 : arrA[0], arrB[0], arrA[1], arrB[1] が、それぞれ別々のオブジェクトを参照しています。
arrA[0][1]の値を変更しても、arrBの中の値は変更されていません。

arrA = Array.new(2){ |i| Array.new(4){ |j| i * 4 + j + 1 } }
p arrA # => [[1, 2, 3, 4], [5, 6, 7, 8]]
arrB = Marshal.load(Marshal.dump(arrA))
p arrA.object_id # => 7977880
p arrB.object_id # => 7977670
p arrA[0].object_id # => 7977870
p arrB[0].object_id # => 7977660
p arrA[1].object_id # => 7977860
p arrB[1].object_id # => 7977650
arrA[0][1] = 10
p arrA # => [[1, 10, 3, 4], [5, 6, 7, 8]]
p arrB # => [[1, 2, 3, 4], [5, 6, 7, 8]]

蛇足で、3次元配列もディープコピーを見てみますと、別々のオブジェクトを参照しているようです。

arrA = Array.new(3){ |i| Array.new(2){ |j| Array.new(3){|k| i * 6 + j * 3 + k + 1 }} }
p arrA # => [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]
p arrA[0] # => [[1, 2, 3], [4, 5, 6]]
p arrA[0][0] # => [1, 2, 3]
arrB = Marshal.load(Marshal.dump(arrA))
p arrA.object_id # => 17830590
p arrB.object_id # => 17830150
p arrA[0].object_id # => 17830580
p arrB[0].object_id # => 17830140
p arrA[0][0].object_id # => 17830570
p arrB[0][0].object_id # => 17830130

(*1)Ruby 2.1.0 リファレンスマニュアル module Marshal

(*2)Ruby 1.8.7 リファレンスマニュアル instance method Object#clone

メソッドの引数(値渡し、参照渡し)

Rubyの引数は値渡しです。

Rubyの引数は値渡しです。参照渡しではありません。ググるとそのようにまとめてらっしゃる方が多々ありますので間違いはないとおもいます。Ruby リファレンスマニュアルで探してみたんですが、記載を見つけられませんでした、確認でき次第アドレスを掲載します。
(*1)参考リンクを追加しました。

ここではRubyの引数(値渡し,参照渡し)について自分なりにまとめてみます。

Rubyist Magazine – 値渡しと参照渡しの違いを理解する

を深く読んでください。を深く読んでください。を深く読んでください。
この記事よりもよっぽど詳しいです。。。

メソッドの復習と名称

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す

値渡しと参照渡し

値渡しと参照渡しについて簡単に説明します。詳細は本当にググってください…

・値渡し (call by value) :実引数として変数を渡しても、その値のみが渡される。そのため、仮引数を変更しても、実変数は変更されない。

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
    p a # => 20
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => 10

・参照渡し (call by variable) :実引数として変数を渡しすとき、変数に対する参照(メモリ番地)先を渡す。そのため、仮引数の値を変更すると、実変数の値も同様に変更されたことになる。

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => 20

注)仮のコードです、rubyでは動作確認できません

引数(実引数)が配列の場合

Rubyは『値渡し』です。しかし、実引数にが配列の場合『参照渡し』のような結果になるときがあります。実引数で渡した配列が、仮引数の値を変更すると実引数の値も変わってしまう『副作用』が生じます。実はこの時『参照の値渡し』と言う値渡しが行われています。
理屈は以前の記事オブジェクトのコピーと同じで、実引数も仮引数も同じオブジェクトを見ている、仮引数にはオブジェクトの参照の値が渡されたということになります。

def hoge(a) # メソッド: hoge, 仮引数: 配列 a
    a[0] += 10 # 配列a[0] に 10 を足す
end

x = [10] # 変数: 配列 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => [20] # 実引数の値が変更されている

objcet_idを確認してみる

def hoge(a)
    a[0] += 10
    p a.object_id # => 17968120
end

x = [10]
p x.object_id # => 17968120
hoge(x)
p x # => [20] # 実引数の値が変更されている

*)object_idで同一性を確認しているだけです。rubyではメモリの番地を調べることはできないようです。

引数(実引数)が配列の場合の『副作用』を予防する

この副作用を予防するには、実引数と仮引数が別のオブジェクトを参照していれば良いということになります。なので、複製を作ればOKになります。

def hoge(a)
  p a.object_id # => 540724920
end

x = [1, 2, 3, 4, 5]
p x.object_id # => 539436540
temp = x.clone
hoge(temp)
def hoge(*a) # * 複数の引数を配列として受け取ります。
  p a.object_id # => 539428060
end

x = [1, 2, 3, 4, 5]
p x.object_id # => 539443780
hoge(*x) # * 展開して渡します

sample01, sample02 もobject_idが違うので、『副作用』は起こりません。

しかし・・・多重配列だと・・・別の機会追記しました。

Rubyist Magazine – 値渡しと参照渡しの違いを理解する

引数 – Wikipedia

*1)お気楽 Ruby プログラミング入門第 3 回●値呼びと参照呼び

変数や定数は,あるオブジェクトを指しています.何も代入しなくても nilオブジェクトを指しています.代入は,変数や定数が新しいオブジェクトを 指すようにします.

したがって,代入によりオブジェクトがコピーされて新しく作られることは なく,右辺の表現の表しているオブジェクトを左辺の変数や定数が指すように することが代入によって行われます.

*1)Ruby FAQ: 変数,定数,引数(文字化けします、EUCで開いてください)

オブジェクトのコピー 【Ruby】

ここでは、オブジェクトを複製するときに注意すること(特に配列オブジェクト)を記述します。
phpでは考えなくてよかったことですが、他の言語ではどうなんでしょうね。

オブジェクトの複製の説明ですが、メソッドの引数にも共通している内容だと思います。
メソッドの引数については、次回触れてみようと思います。(値渡し,参照渡し)

少し復習

rubyでは変数も何かのオブジェクトです。

変数『a』という箱に”cototoco”という文字を入れたイメージですが、「String(文字列)オブジェクト”cototoco”に、『a』とラベルを付けた」と、言うとらえ方もsample0よりわかります。
*)変数はオブジェクトにつける名札 Ruby リファレンスマニュアルの用語集 変数より

a = "cototoco"
p a.class # => String
p a.object_id # => 540010740

注) すべてオブジェクトと記載しようとして思い調べてみたら、違うようです。
メソッド,ブロック,演算子のand, or 等々はオブジェクトではないとのことです。
Rubyでは、すべてがオブジェクト。じゃないよ! – このブログは証明できない。

オブジェクトのコピー[導入部]

文字列オブジェクト『a』を『b』に代入してみます。
『a』と『b』のobject_idが同じ値になっていることから、ラベルの違う『a』と『b』は同じオブジェクトを参照していることが分かります。同じオブジェクトなので、内容も同じです。しかし、object_idが1つなのでオブジェクトはコピー(複製)されていません。

a = "cototoco"
p a.class # => String
p a.object_id # => 540009530
b = a
p b.class # => String
p b.object_id # => 540009530

ここで、『a』に別の値を入れてみます。
すると、『a』は初期化されので、新しいobject_idが振られていることが分かります。
『a』と『b』は別々のオブジェクトになり、中の文字列も別々の値になっています。
『a』の値を変更しても、『b』の値は保持されているので、複製の目的は成り立っています。

# sample1の続き
a = ".net"
p a.object_id # => 539434520
p b # => "cototoco"
p b.object_id # => 540009530

オブジェクトのコピー[本題]

さて、『a』が配列オブジェクトの場合もStringオブジェクトと同様の結果になりますが、少し注意することが必要です。
『a』の配列の中の値を変更する場合、『b』の値も変更されてしまいます。

a[1]の値を変更した結果、b[1]の値も変更されています。不思議に感じますが、object_idを調べてみると『a』と『b』は同じオブジェクトを参照していることがわかります。『a』と『b』の参照先は同じなので、『a』を変更するということは、『b』を変更することになります。

a = [3, 7, 9, 2]
b = a
p a[1] # => 7
a[1] = 10
p a # => [3, 10, 9, 2]
p b # => [3, 10, 9, 2]
a.object_id # => 540642090
b.object_id # => 540642090

『a』と『b』を別々のオブジェクトにするとこの動作がなくなります。

1, 『a』を初期化する。sample2の様に、『a』に改めて値を代入します。

a = [3, 7, 9, 2]
b = a
a = [3, 10, 9, 2]
p a # => [3, 10, 9, 2]
p b # => [3, 7, 9, 2]
a.object_id # => 539950350
b.object_id # => 539958810

2, clone, dup メソッドを使う。
cloneメソッドはオブジェクトの複製を返すメソッドです。(リファレンスマニュアル

a = [3, 7, 9, 2]
b = a.clone
a[1] = 10
p a # => [3, 10, 9, 2]
p b # => [3, 7, 9, 2]
a.object_id # => 540474720
b.object_id # => 540331010

配列オブジェクトの複製は、cloneメソッドsample5かsample4の方法を持ちいりましょう。

破壊的メソッドはレシーバ自身を変更する

以前の記事、配列 メソッドについてのように、破壊的メソッドはレシーバ自身を変更します。
この時、意図せずsample3パターンにはまってしまう時があります。

例えば、配列『arr_a』に値を追加する時、現在の値を『temp』に保存する場合を考えます。
配列に値を追加するメソッドにpushがあります。pushは破壊的メソッドなのでレシーバを変更します。
では、『arr_a』を『temp』に保存し、『arr_a』にpushで値を追加してみます。

arr_a = [3, 7, 9, 2]
temp = arr_a
arr_a.push(100)
p temp # => [3, 7, 9, 2, 100]

状態を保存したはずの『temp』の値まで変更されてしまいました。
このようなときはsample5のように、cloneメソッドを持ちいりましょう。

Rubyでは、すべてがオブジェクト。じゃないよ! – このブログは証明できない。
リファレンスマニュアル