Composer
- ストレス開発駆動
- 3年続けた結果できたよー
大量のデータを困ってませんか?
- Cronバッチが終わらない…
- 馬鹿みたいにでかいデータの対処…
BigQuery in GCP
Full Managed.
- AWS RedShift
- 落とすに落とせないのと、時間課金なのでおかねかかる
Github が Google のこれを使って何かを解析しているみたい。
BigQuery
- RDB ではない。
- MapReduce で使える
- 癖ある
- WebAPI
- PHPライブラリある
- RedShift は PostgreSQL 互換なので Libpq でつながる
- WebAPIなので対象言語幅は広くて楽
- PHPライブラリある
Data Import
- Load
- GCS Google Cloud Storage
- ファイルアップロード
- Stream Insert
- 0.01$/200 MB
- 基本無料
- Copy
- Table to Table
- Select
- $5 / 1TB
- 1TB/Monthly 無料
- Select * from T1,T2,T3 → Union になる
- Googleの中の人「これは失敗だった」
- $5 / 1TB
癖
- 頑張ってIndexを張ったり、SQLを改善して速くなることはない
- 集計で裏で回してデータ保存させる手法でやる
- ResourceOver の下限がわからない
- 中の人「リミットを11にしたらいけるんじゃない(金払え)」
- Selectしかない
- Update は無い
- Delete は無い
- テーブルのデータを変えたいなら、テーブル消して、ロードする
おかね
- データ保存料金は安い
- すぐに使いたいならお金を払えばいいみたい
- クエリー料金
- 料金発生ポイント
- select name,address from ds.member where age >= 30 limit 100
- name,address の列のデータ量に対して料金発生
- age の列のデータ量に対して料金発生
- select * from ds.member
- 全ての列のデータ量になるので使っちゃダメ
- table名に日付を付けれる
- 日付rangeを付けられる
- 10TB Limit がある
- 料金発生ポイント
注意事項
- 500/503 エラーが多い
- Googleイベントがあるとエライことになる
ORMユーザ対談
お昼後なので眠いでござる。
- ORM 実装が沢山あって、それぞれの違いを知りたい
PDO
<?php
$stmt = $pdo->query('select * from books where id=1;');
$book = $stmt->fetch();
$book['title'];
Eloquent ORM
In Laravel.
- Model を継承してActiveRecodeっぽいかんじ
class Book extends Illuminate\Database\Eloquent\Model\Model {}
$book = Book::find(1);
$book->title;
Doctrine
- Symfonyで
- 何も継承しない
- Javaから続く伝統的なORM
class Book
{
private $id;
private $title;
}
$repo = $doctrine->getRepository('BookBundle:Book');
$repository->find(1)->getTitle();
CakePHP
- CakePHP2 は配列
- CakePHP3 はEntityObject
- 規約ベースなので、テーブルが規約に則っていれば、クラスは作らなくても取得できる
<?php
class BooksTable extends Cake\ORM\Table {}
class Book extends Cake\ORM\Entity {}
$table=TableRegistry::get('Books')->get(1)->title;
関連性
select * from books left join authors on authors.id = books.author_id;
Eloquent
<?php
class Book extends Model
{
public function author() { return $this->belongsTo(Author::class); }
}
// 二つのSQLを発行
Book::find(1)->author->name;
Cake
<?php
class BooksTable extends Table
{
public function initialize(array $config){
param::initialize($config);
$this->belongsTo('Authors');
}
}
// ..どうやってとる?
Doctrine
アノテーションに書く。ながい…
EAGER => join した形。
N+1問題
EAGER/LAGER 問題
Eloquent
それぞれ別々のクエリーを延滞発行するので、必要分投げる。
<?php
$books = Book::with('author')->get();
最低でも二回SQLは出る。
Doctrine
基本はLagerだけど、取った分のキャッシュをする。EntityManager がレイジーの発生はauthor数まで。
CakePHP
Lager 機能ないので、LagerLoadPluginを入れないとだめ。なので基本 join する。
オブジェクトの同一性
$author->books[0]->author; これは同じ?
CakePHP
$author->books[0]->author; は取ってこれない。
Eloquent
無頓着。もっかい取りに行くだけ。
Yii2
(なぜ今頃…)
->inversedOf('author');
Doctrine
$author->getBooks()[0]->getAuthor()
- EntityManager が扱っているので、
100万件バッチ処理
PHPのMySQLが死ねる。
Cake3
PDOのfetchが走る。今はデフォルトではないけど、オプションで mysql_buffer_query:true
にしてやる必要があるっぽい。
(三年分の競馬データが回せた)
他は?
- Eloquentは死にますので、chunkメソッドでlimit/offsetを使え。
- Doctrine は死にます。DBRMでlimit/offsetを使う。
残り
3秒で終わり
Laravel DI Container
みかかねさん
conteinr への登録
<?php
// シングルトン
app()->singleton(User::class, function(){
return new User();
});
// 毎回新規作成する
app()->bind(HogeService::class, HogeService::class);
// 取得 / 登録してなくても自動的にnewする
$hoge = app(HugaService::class);
ライブラリ化のバージョニング
- git subtree
- Composer Path Repository
- type:"path",url:"./lib/auth/"
- vendor 外にあるディレクトリをautoloadに入れる
- repository に type:path を入れると良い
PHPerに知ってほしいRDBの事
DBの寿命はAppより長い = 付き合いが長くなっていく。
sodaiさん
対象DB
MySQL5.7 / PostgreSQL9.5?
活用事例/Security の話はしない。
検索とIndex
検索: Btree Index => where/GroupBy/OrderBy で使われる
- MySQL は検索時にIndexは一つしか使わない。
- 重複が少ないほうが良い
- 結果が少ないほうが良い
- 全体10%〜30%の少ないと使う
実行計画
- Explain をみる
- レコードを実レコードに合わせる
- 統計情報を最新にする
- 本番からdumpして、ローカルに入れても少ないままなので、refreshする必要ある
- 実行結果が正しいことを試す
- 素振り大事
- MySQL Workbench
- 虫眼鏡マークのボタンを押すと実行計画を見せてくれる
- 赤(インデックス聞いていない
- 黄色(将来遅くなるかも
- 緑
- 青(最速
- 相関サブクエリは遅い
- Index効いているとJoinと同じように速くなる
- Joinは掛け算(100行x100行)
- Joinはアルゴリズムの一つ
- Joinするなら
- データを小さくしてから
- Index を利用したJOINをする
- 正規化大事
- シンプル・拘束
- 難しいことをしない設計力が大事
- 虫眼鏡マークのボタンを押すと実行計画を見せてくれる
- PostgreSQL
- Indexは複数使える
- そもそもINDEXたくさんある
- 相関サブクエリは速い
- JOINのアルゴリズムも複数ある
- 式INDEX
- substr とか使っても、実行結果Indexを使うことができる
- でもRDBの基本はMySQLと一緒
- MySQL Workbench
Schemaless
正規化の話
- データは
- 消せない
- 変更できない
- 追加で対応
- 不整合が内容にするために
- 正規化!
- ジェイウォークはなぜダメ?
- 検索死ぬ 京都の検索で東京都
- 集計で死ぬ できない…
- 更新ができない 部分更新ができない
- 回答者と質問と回答を別々にする
- スキーマ変更しなくてもいいように
- MySQL => JSON型(5.7〜), PostgreSQL -> JSON型
- 正しいJSONであることが担保
- インデックスはれる
- mysql
select * from demo_json where json_extract(properties '$.name') like 'hoge';
- 仮想列を作って、Indexをはる(5.7.5~)
- 制約ができない(Unique制約や外部キー制約がない)
- 自由な保存と正しく守る、はトレードオフ
- 使うのにOKな時
- JSONと他のテーブルが直接関係しない
- 中の値をUPDATEしない
- INSERT/SELECTが大半の構造
- そもそもORMが死ぬ
- ご利用は計画的に。
- 使うのにOKな時
アンチパターン
- DELETE_FLAG
- 9とかNULLが入っている(なぜ9…?)
- 非正規化
- 基本的に正規化したほうが速い
- 少ないデータだと、キャッシュでメモリーに残っている事が多い
- 外部キーレス設計
- 正規化も外部キー制約もデータを守るためにある
- そもそもRDB勉強しよう
- データベース実践入門・SQLアンチパターン
- 使い方も大事
- 10年戦えるデータ分析入門
- SQLデータ入門
- ある日突然重くなる
- DB は蛇口、コップはメモリー、コップはあふれた瞬間に重くなる
まとめ
- ドキュメントみる
- 実行計画を見る
- DB問題は忘れた頃にやってくる
- サーバ問題は休日中に来る
- アプリケーション問題は納期前にくる
- RDBの知識は寿命が長い
- 覚えていれば長い間役に立つ
- データが死ねば皆死ぬ
- RDBは歴史長い→いろんな経験談から学ぶ
RDBはいいぞ