LoginSignup
3
4

More than 5 years have passed since last update.

PHPKansai 2016 Memo

Posted at

Composer

  • ストレス開発駆動
  • 3年続けた結果できたよー

大量のデータを困ってませんか?

@kunit

  • Cronバッチが終わらない…
  • 馬鹿みたいにでかいデータの対処…

BigQuery in GCP

Full Managed.

  • AWS RedShift
    • 落とすに落とせないのと、時間課金なのでおかねかかる

Github が Google のこれを使って何かを解析しているみたい。

BigQuery

  • RDB ではない。
  • MapReduce で使える
  • 癖ある
  • WebAPI
    • PHPライブラリある
      • RedShift は PostgreSQL 互換なので Libpq でつながる
    • WebAPIなので対象言語幅は広くて楽

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の中の人「これは失敗だった」

  • 頑張って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と一緒

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が死ぬ
      • ご利用は計画的に。

アンチパターン

  • DELETE_FLAG
    • 9とかNULLが入っている(なぜ9…?)
  • 非正規化
    • 基本的に正規化したほうが速い
    • 少ないデータだと、キャッシュでメモリーに残っている事が多い
  • 外部キーレス設計
    • 正規化も外部キー制約もデータを守るためにある
  • そもそもRDB勉強しよう
    • データベース実践入門・SQLアンチパターン
    • 使い方も大事
      • 10年戦えるデータ分析入門
      • SQLデータ入門
  • ある日突然重くなる
    • DB は蛇口、コップはメモリー、コップはあふれた瞬間に重くなる

まとめ

  • ドキュメントみる
  • 実行計画を見る
  • DB問題は忘れた頃にやってくる
  • サーバ問題は休日中に来る
  • アプリケーション問題は納期前にくる
  • RDBの知識は寿命が長い
    • 覚えていれば長い間役に立つ
    • データが死ねば皆死ぬ
    • RDBは歴史長い→いろんな経験談から学ぶ

RDBはいいぞ

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4