SlideShare a Scribd company logo
1
ソーシャルゲーム案件における
DB 分割の PHP 実装
~とにかく分割ですよ。 10 回じゃ足りない。 20 回くらい分割。~
株式会社インフィニットループ
佐々木 亨基
自己紹介
・佐々木 亨基
・ゆきこ yukicon
・ Twitter:@yukiconEx
・株式会社インフィニットループ所属
・札幌 MySQL 勉強会代表
・ PHP 歴は 4 年くらい
・現在仕事では PHP オンリー
・いい加減な人間なので PHP の緩さは好き
インフィニットループについて
・北海道札幌市にあるシステム開発会社
 約 90 名(契約スタッフ・アルバイト含む)で活動中
 社長も含め、ほぼ全員がエンジニア
・主な開発実績(主にサーバサイドを担当)
 ブラウザ三国志 (2009)
 英雄クエスト (2010)
  Lord of Knights(2012)
 フォトバトラー (2012)
  Vim 検定 (2012)
  PHP 検定 (2013)
 その他いろいろ
お題目
■ はじめに
・ DB 分割とは
・どうして DB 分割なんかするの?
・ユーザ単位による水平分割
・ DB 分割のデメリット
お題目
■ 実装のお話
・クラス設計
・使用例
・エイリアス
・水平分割
・水平分割された DB への問い合わせ
・トランザクション
・トランザクションの開始
・コミット
・まとめ
DB 分割とは
分割していない DB
A テーブル
B テーブル
C テーブル
D テーブル
E テーブル
F テーブル
DB 分割とは
分割した DB
A テーブル
B テーブル
E テーブル
F テーブル
E テーブル
F テーブル
E テーブル
F テーブル …
垂直分割
( テーブル単位での分割 )
水平分割
( 同テーブルの ID 単位による分割 )
C テーブル
D テーブル
DB 分割とは
更にそれぞれがマスタスレーブ構成を取る
Master
Master
…
垂直分割
( テーブル単位での分割 )
水平分割
( 同テーブルの ID 単位による分割 )
Slave Slave Slave
Master
Slave Slave Slave
Slave Slave Slave
Master
Slave Slave Slave
Master
Slave Slave Slave
どうして DB 分割なんかするの?
■ 要件
数万~十数万の同時接続数に耐えられるシステム
■ 案件の特徴
ソーシャルゲーム案件の規模は予測が難しい
突然跳ねる事もあり、正確な規模が見積もれない
どうして DB 分割なんかするの?
・同時接続数万という要求は高い
・さらに予想を上回る可能性もある
・しかしその実さっぱり流行らない可能性もある
・スモールスタート可能
・かつ困った時にサーバ追加で解決できる構成
つまり
スケールアウト可能なシステム構成
どうして DB 分割なんかするの?
Web サーバは単純なサーバ追加で対応可能
しかし DB は簡単にはいかない
・・・ ×nWeb Web Web Web
DB × ?
どうして DB 分割なんかするの?
DB のスケールアウトと言えばマスタスレーブ構成
Master
Slave Slave Slave ・・・ ×n
SELECT
UPDATE
SELECT SELECT
どうして DB 分割なんかするの?
しかしマスタスレーブ構成のマスタサーバは 1 台
マスタサーバの更新性能がネックとなり
いずれ限界が来る
Master
Slave Slave Slave ・・・ ×n
SELECT
UPDATE
SELECT SELECT
どうして DB 分割なんかするの?
マスタ 1 台で数万の同時接続数を捌くのは不可能
要件的にマスタスレーブ構成では破綻する
どうして DB 分割なんかするの?
ではどうする?
・ Fusion-io のような超高速ストレージを使う?
 →用意できるとは限らない
 →導入しても解決しなかった場合に詰む
・ MySQL Cluster を使う?
 →まだ枯れていない技術という印象
 →制約も多く、導入は怖い
どうして DB 分割なんかするの?
マスタスレーブのセットを増やそう !
       |
   \   __   /
    _ (m) _ピコーン
       | ミ |
    /  ` ´   \
      ('A`)
     ノヽノヽ
       くく
ユーザ単位による DB 分割
ユーザ数が増えたなら UserDB を追加
Global が苦しくなったら更に垂直分割をする事で
スケールアウト可能
User1 User2 User3 …
水平分割された UserDB
ユーザに紐付くデータを一定のルールで振り分けて格納
Global
GlobalDB
ユーザに紐付かない共通のデータを格納
DB 分割のデメリット
■ 設計でカバーする
・ DB 間を跨いだ JOIN ができない
→ 冗長なデータの持ち方をしてしまう
→ マスタデータは全 DB に持つなどして対策
・水平分割すればするほどパフォーマンスが下がる
 ※とにかく分割とかいうタイトルになってますが
  あんまり分割しちゃダメです、最低限にしましょう
DB 分割のデメリット
■ できるだけライブラリ側で吸収する
・水平分割された DB の串刺し検索が大変
→ ユーザ一覧を持ってくるのですら一苦労
・複数 DB のトランザクション管理が煩雑
ここからは実装のお話
クラス設計
3 つのクラスから成っている
・ DatabaseAccess
 全 DB 、トランザクションを統括するクラス
・ DatabaseAccessNode
 単一 DB にアクセスするクラス
 マスタスレーブの切り替えも行う
 分割なしならこのクラスのみで完結
・ DatabaseAccessMultiNode
 水平分割された DB にまとめてアクセスするクラス
クラス設計
図にすると
Master
Master
…
DatabaseAccess
Slave Slave Slave
Master
Slave Slave Slave
Slave Slave Slave
Master
Slave Slave Slave
Master
Slave Slave Slave
DatabaseAccessNode
DatabaseAccessMultiNode
使用例
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->getDBAN('global')->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->getDBAN('user', $user_id)->select('user_tbl');
// 複数の対象ユーザ DB から SELECT
$dban_arr = $dba->getDBANArr('user', $user_id_arr);
$dbam = new DatabaseAccessMultiNode($dban_arr);
$dbam->select('user_tbl');
使用例
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->getDBAN('global')->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->getDBAN('user', $user_id)->select('user_tbl');
// 複数の対象ユーザ DB から SELECT
$dban_arr = $dba->getDBANArr('user', $user_id_arr);
$dbam = new DatabaseAccessMultiNode($dban_arr);
$dbam->select('user_tbl');
なんか難しい!
エイリアス
エイリアスをつくって抽象化
class DatabaseAccess
{
function gb()
{
// global の DatabaseAccessNode オブジェクトを返す
return $this->getDBAN('global');
}
function user($user_id)
{
// user の DatabaseAccessNode オブジェクトを返す
return $this->getDBAN('user', $user_id);
}
:
:
エイリアス
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->gb()->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->user($user_id)->select('user_tbl');
// 複数のユーザ DB から SELECT
$dba->user_multi($user_id_arr)->select('user_tbl');
だいぶすっきり
エイリアス
// singleton なインスタンスを取得
$dba = DatabaseAccess::getInstance();
// グローバル DB から SELECT
$dba->gb()->select('user_id_tbl');
// 対象ユーザ ID のデータがある DB から SELECT
$dba->user($user_id)->select('user_tbl');
// 複数のユーザ DB から SELECT
$dba->user_multi($user_id_arr)->select('user_tbl');
// 全ユーザ DB から SELECT
$dba->user_all()->select('user_tbl');
全ユーザ DB 用のエイリアスも用意すると便利
水平分割
ID とサーバ ID をマッピングするテーブルを
グローバル DB に作成して管理
CREATE TABLE `id_partition_tbl` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`server_id` tinyint(4) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `server_id` (`id`,`server_id`)
)
id server_id
1000 1
1001 2
1002 3
水平分割
ID の発行 ( 仮に server_id を 1 で指定 )
INSERT INTO id_partition_tbl (server_id) VALUE (1);
SELECT LAST_INSERT_ID();
 ↓
分割ルールに従ってサーバの割り当て
 ↓
テーブルへの登録
UPDATE id_partition_tbl SET server_id = 3 WHERE id = 1000;
水平分割
分割ルール
・テーブルによる管理
必ずテーブルを参照する必要がある
server_id をキャッシュするなどの工夫が必要
登録数の少ないサーバに振り分け
各サーバに重みをつけて振り分け
既存データを意図通りに再配置
など柔軟な対応が可能
$server_id = getServerId('id_partition_tbl', $id);
水平分割
分割ルール
・剰余やハッシュによる振り分け
均等にバランシングされる
サーバ追加時に既存データの再配置が必要
$server_id = ($id % $server_cnt) + 1;
水平分割
分割ルール
・範囲による振り分け
ある程度意図を持ってバランシングできる
既存データに手をいれずサーバ追加が可能
ただし小回りは効かない
foreach ($range_arr as $range) {
if ($range['min'] <= $id and $id <= $range_info['max']) {
$server_id = $range['server_id'];
break;
}
}
水平分割された DB への問い合わせ
DatabaseAccessMultiNode クラスにより実現
複数 DB に同じ SQL を投げ、結果をマージ
使用者は複数 DB への問い合わせである事を意識
せず、単一 DB を扱うのと同様に記述する事がで
きる
// 単一 DB への問い合わせ
$dba->user($user_id)->select('user_tbl');
$dba->user($user_id)->update('user_tbl');
// 複数 DB への問い合わせ
$dba->user_multi($user_id_arr)->select('user_tbl');
$dba->user_multi($user_id_arr)->update('user_tbl');
水平分割された DB への問い合わせ
__call と call_user_func_array によって実装
DatabaseAccessNode クラスに単一 DB へ問い合
わせる処理を追加すると、
DatabaseAccessMultiNode クラスを経由して複
数 DB に問い合わせもする事ができる
class DatabaseAccessMultiNode
{
function __call($func_name, $args = array())
{
// 各 DB に対して実行
foreach ($this->dban_arr as $key => $dban) {
$tmp_data_arr[] =
call_user_func_array(array($dban, $func_name), $args);
}
水平分割された DB への問い合わせ
レスポンスは型によって処理を振り分ける
$tmp_data = reset($tmp_data_arr);
if (is_numeric($tmp_data)) {
// 数値の場合は和を返す
$sum = 0;
foreach ($tmp_data_arr as $tmp_data) {
$sum += $tmp_data;
}
return $sum;
} else if (is_array($tmp_data)) {
// 配列の場合はマージして返す
$data = array();
foreach ($tmp_data_arr as $tmp_data) {
$data = array_merge($data, $tmp_data);
}
return $data;
:
:
水平分割された DB への問い合わせ
user_id をキーにした場合
UPDATE は対象レコードが存在しないため問題無いが
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
UPDATE t SET a = a + 100 WHERE
user_id IN (1000, 2000, 3000);
水平分割された DB への問い合わせ
INSERT は気をつける必要がある
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
水平分割された DB への問い合わせ
INSERT は気をつける必要がある
User1
(1000-1999)
User2
(2000-2999)
User3
(3000-3999)
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
INSERT INTO t (user_id, a) VALUES
(1000, 0), (2000, 0), (3000, 0);
不要なレコードまで INSERT されてしまう
水平分割された DB への問い合わせ
__call による実装は、あくまでも全 DB に同じ
クエリを投げているだけ
レスポンスも型によって機械的に対応している
INSERT のようにそれでは問題がある場合は、
専用メソッドを立てて対応する
トランザクション
トランザクションは DB 単位でかかるため
管理に気を使わなくてはいけない
// 対象のユーザ DB にトランザクション開始
$dba->beginTransactionToUser($user_id);
// この更新はグローバル DB への更新のため
// トランザクションの対象とならない
$dba->gb()->update();
XA トランザクション…
うっ…頭が…
( 分離レベルが SERIALIZABLE に限られる、
 挙動が怪しいという事で、ミドルウェアに頼らず
 アプリによる実装としました )
トランザクションの開始
複数 DB へのトランザクション開始方法は 2 通り
・最初にまとめて開始してしまう
・必要になった時点で開始する
トランザクションが必要な事がわかりきっている場合は最
初にまとめてしまう方が管理が楽かつ簡単
どれか 1 つでもトランザクションがかかっていれば他の DB
も更新処理時に自動でトランザクション状態となるオート
モードも用意したが、管理できなくなる懸念があったため
使っていない
トランザクションの開始
■ 最初にまとめて開始してしまう場合
トランザクションは短い方が良い
コネクションのコストによって無用にトランザクションが
長くならないようにマスタサーバへのコネクションを行
なってからまとめてトランザクションを開始する
// 対象の DB をマスタに接続
$dba->gb()->useMaster();
$dba->user($user_id)->useMaster();
// マスタに接続した DB を一斉にトランザクション開始
$dba->myBeginTransactionToConnectionMaster();
Global User
コネクション
BEGIN
コネクション
BEGIN
Global User
コネクション
コネクション
BEGIN
BEGIN
トランザクションの開始
■ 必要になった時点で開始する場合
ある DB に対してトランザクションをかけるが、
ある DB に対しては 10 回に 1 回くらいしかトランザクショ
ンが必要が無い処理の場合、必要になった時にトランザク
ションを開始する
別々のユーザ ID が対象になった際に両方のユーザ ID が同
じ DB に所属している場合など、既にトランザクションが開
始されている事もある
// 対象のユーザ DB にトランザクション開始
$dba->beginTransactionToUser($user_id);
// たまにしかここに来ないので、ここでトランザクション開始
// 既にトランザクション開始されているならスルーする
If ($dba->user($other_user_id)->isTransaction()) {
// 同じ DB の場合はここにはこない
$dba->beginTransactionToUser($other_user_id);
}
コミット
各 DB に対してバラバラのタイミングでコミットを行うとつ
くりが複雑になり、データ不整合となるバグを引き起こす
可能性が高くなる
悪い例
// グローバル DB をアップデート
$dba->gb()->update();
// グローバル DB をコミット
$dba->commitToGlobal();
// ユーザ DB をアップデート
$dba->user($user_id)->update();
// ユーザ DB をコミット
$dba->commitToUser($user_id);
ここでエラーが起こるとユーザ DB のみ更新されず
データ不整合状態となる
Global User
UPDATE
COMMIT
UPDATE
COMMIT
コミット
コミットは必ず処理の最後にまとめて行うようにする
処理の順番によるデータ不整合に気を配る必要が無くなり
コーディングの難易度も下がる
// グローバル DB をアップデート
$dba->gb()->update();
// ユーザ DB をアップデート
$dba->user($user_id)->update();
// まとめてコミット
$dba->allCommit();
Global User
UPDATE
UPDATE
COMMIT
COMMIT
コミット
まとめてコミットと言っても順番にコミットするだけ
いわゆる 2 相コミットではないため、一部がコミットされ
てしまうと全体のロールバックは不可能
やはり途中でエラーとなった場合はデータ不整合となる
$commited_arr = array();
foreach ($dban_arr as $dban) {
$dban->commit();
$commited_arr[] = $dban->database_name;
}
コミット
途中でコミットがエラーとなった場合は、どの DB がコミッ
トされ、どの DB がコミットされていないのかをログに残す
} catch (Exception $e) {
if (0 < count($commited_arr)) {
// 1 度以上コミットしたということはデータ不整合
$uncommited_arr = array();
foreach ($dban_arr as $dban) {
if ($dban->isTransaction()) {
// トランザクション中なら配列に含める
$uncommited_arr[] = $dban->database_name;
}
}
// エラーとなった DB 情報のログを残す
logging(sprintf('commit error commited[%s]
uncommited[%s]', implode(',', $commited_arr),
implode(',', $uncommited_arr)));
}
}
コミット
ログを頼りに手で対応する事になってしまうが
実際データ不整合はほとんど起こらず
1 年で 1 回や 2 回という低い頻度のため
ログによる対応で問題となった事はない
まとめ
・エイリアスを用意
・複数 DB を束ねて管理するクラスを用意
抽象化は重要
抽象化する事で経験の浅いエンジニアでも扱える
・分割ルールは設計段階で破綻の無いように決めておく
必要であれば独自のルールによる振り分けを実装する
・トランザクションの管理もできるだけ簡単にする
・特にコミットはデータ不整合の起こりやすいポイント
・ 2 相コミットではない
・一部コミットされると全体ロールバックは不可
・データ不整合はコミット失敗のログを残す事で対応する
DB 分割意外となんとかなる
でも気をつけるところはちゃんと気をつけないとダメ
求人募集
インフィニットループでは、エンジニアを募集しています
・社長も含めほぼ全員がプログラマで技術者に優しい環境
・勤務地は北海道札幌市、他社出向などは無し
・おいしい食べ物、自然いっぱい、花粉少ない、涼しい
・短い通勤時間、徒歩や自転車で通勤が可能
・ U ターン、 I ターン大歓迎
・ PHP 開発エンジニア
・スマホ開発エンジニア
・ MySQL エンジニア
・インフラエンジニア
ご清聴ありがとうございました

More Related Content

What's hot (20)

PPTX
ゲームエンジニアのためのデータベース設計
sairoutine
 
PDF
ヤフー社内でやってるMySQLチューニングセミナー大公開
Yahoo!デベロッパーネットワーク
 
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
 
PDF
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
Amazon Web Services Japan
 
PDF
MHA for MySQLとDeNAのオープンソースの話
Yoshinori Matsunobu
 
PDF
SQL大量発行処理をいかにして高速化するか
Shogo Wakayama
 
PDF
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
Yahoo!デベロッパーネットワーク
 
PPTX
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
toshi_pp
 
PDF
新入社員のための大規模ゲーム開発入門 サーバサイド編
infinite_loop
 
PDF
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
 
PPTX
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
 
PDF
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
NTT DATA Technology & Innovation
 
PPTX
BuildKitによる高速でセキュアなイメージビルド
Akihiro Suda
 
PDF
社内Java8勉強会 ラムダ式とストリームAPI
Akihiro Ikezoe
 
PPTX
地理分散DBについて
Kumazaki Hiroki
 
PDF
Where狙いのキー、order by狙いのキー
yoku0825
 
PDF
PHPからgoへの移行で分かったこと
gree_tech
 
PDF
The Twelve-Factor Appで考えるAWSのサービス開発
Amazon Web Services Japan
 
PDF
MySQLで論理削除と正しく付き合う方法
yoku0825
 
PPTX
トランザクションの設計と進化
Kumazaki Hiroki
 
ゲームエンジニアのためのデータベース設計
sairoutine
 
ヤフー社内でやってるMySQLチューニングセミナー大公開
Yahoo!デベロッパーネットワーク
 
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
 
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
Amazon Web Services Japan
 
MHA for MySQLとDeNAのオープンソースの話
Yoshinori Matsunobu
 
SQL大量発行処理をいかにして高速化するか
Shogo Wakayama
 
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
Yahoo!デベロッパーネットワーク
 
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
toshi_pp
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
infinite_loop
 
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
 
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
 
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
NTT DATA Technology & Innovation
 
BuildKitによる高速でセキュアなイメージビルド
Akihiro Suda
 
社内Java8勉強会 ラムダ式とストリームAPI
Akihiro Ikezoe
 
地理分散DBについて
Kumazaki Hiroki
 
Where狙いのキー、order by狙いのキー
yoku0825
 
PHPからgoへの移行で分かったこと
gree_tech
 
The Twelve-Factor Appで考えるAWSのサービス開発
Amazon Web Services Japan
 
MySQLで論理削除と正しく付き合う方法
yoku0825
 
トランザクションの設計と進化
Kumazaki Hiroki
 

Viewers also liked (6)

PDF
PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発
infinite_loop
 
PDF
Amebaソシャゲ分析事例のご紹介
Masanori Takano
 
PDF
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
infinite_loop
 
PDF
サーバー未経験者がソーシャルゲームを通して知ったサーバーの事
Manabu Koga
 
PPTX
データに振り回されて失敗した あんなことやこんなこと ~ゲームのために必要な本当の ビジネス・アナリティクス~
Daisuke Nogami
 
PDF
CEDEC2013 ソーシャルゲームの開発現場でUXについて思いっきりあがいてみた1年間の話
Takahiro YAMAGUCHI
 
PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発
infinite_loop
 
Amebaソシャゲ分析事例のご紹介
Masanori Takano
 
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
infinite_loop
 
サーバー未経験者がソーシャルゲームを通して知ったサーバーの事
Manabu Koga
 
データに振り回されて失敗した あんなことやこんなこと ~ゲームのために必要な本当の ビジネス・アナリティクス~
Daisuke Nogami
 
CEDEC2013 ソーシャルゲームの開発現場でUXについて思いっきりあがいてみた1年間の話
Takahiro YAMAGUCHI
 
Ad

Similar to ソーシャルゲーム案件におけるDB分割のPHP実装 (20)

PDF
PerlとSQLのいろいろ
Takuya Tsuchida
 
PDF
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
azuma satoshi
 
PDF
MongoDB2.2の新機能
Shoken Fujisaki
 
PPTX
Ruby on Rails on MySQL チューニング入門
だいすけ さとう
 
KEY
My sql casual_in_fukuoka_vol1
Makoto Haruyama
 
PDF
Heroku Postgres
Salesforce Developers Japan
 
PDF
Heroku Postgres
Ayumu Aizawa
 
PDF
Google Gears データベースの基礎
webos-goodies
 
PDF
【第3回初心者勉強会】データベースを使おう
Shuhei Iitsuka
 
PDF
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
歩 柴田
 
PDF
Web技術勉強会 20100925
龍一 田中
 
PDF
InnoDBのすゝめ(仮)
Takanori Sejima
 
PDF
分割と整合性と戦う
Yugo Shimizu
 
PDF
Random partionerのデータモデリング
2t3
 
PDF
JPUGしくみ+アプリケーション勉強会(第20回)
Yoshinori Nakanishi
 
PPTX
PHP基礎勉強会
Yuji Otani
 
PDF
MySQL 5.5 Update #denatech
Mikiya Okuno
 
PDF
DTraceによるMySQL解析ことはじめ
Mikiya Okuno
 
PPT
今年こそ始めたい!SQL超入門 セミナー資料 2024年5月22日 富士通クラウドミートアップ
Toru Miyahara
 
PPTX
1.2新機能と1.2から始めるcql3
seki_intheforest
 
PerlとSQLのいろいろ
Takuya Tsuchida
 
Perl暦およそ10年(?)の僕がデータベースを使えるようになるまでの昔話
azuma satoshi
 
MongoDB2.2の新機能
Shoken Fujisaki
 
Ruby on Rails on MySQL チューニング入門
だいすけ さとう
 
My sql casual_in_fukuoka_vol1
Makoto Haruyama
 
Heroku Postgres
Ayumu Aizawa
 
Google Gears データベースの基礎
webos-goodies
 
【第3回初心者勉強会】データベースを使おう
Shuhei Iitsuka
 
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
歩 柴田
 
Web技術勉強会 20100925
龍一 田中
 
InnoDBのすゝめ(仮)
Takanori Sejima
 
分割と整合性と戦う
Yugo Shimizu
 
Random partionerのデータモデリング
2t3
 
JPUGしくみ+アプリケーション勉強会(第20回)
Yoshinori Nakanishi
 
PHP基礎勉強会
Yuji Otani
 
MySQL 5.5 Update #denatech
Mikiya Okuno
 
DTraceによるMySQL解析ことはじめ
Mikiya Okuno
 
今年こそ始めたい!SQL超入門 セミナー資料 2024年5月22日 富士通クラウドミートアップ
Toru Miyahara
 
1.2新機能と1.2から始めるcql3
seki_intheforest
 
Ad

More from infinite_loop (20)

PDF
ChatGPT触ってみた
infinite_loop
 
PDF
社内ソフトスキルを考える
infinite_loop
 
PDF
3Dプリンタって いいね
infinite_loop
 
PDF
VRChatでお酒が注げる飲み物アセットの紹介
infinite_loop
 
PDF
アニメーションとスキニングをBurstで独自実装する.pdf
infinite_loop
 
PDF
I ❤ Virtual Machines 仮想環境をより便利に使うツールたち
infinite_loop
 
PDF
500万行のPHPプロジェクトにおけるログ出力の歩み
infinite_loop
 
PDF
ADRという考えを取り入れてみて
infinite_loop
 
PDF
リファクタリングで実装が○○分短縮した話
infinite_loop
 
PDF
ゲームのインフラをAwsで実戦tips全て見せます
infinite_loop
 
PDF
楽しいVR空間を作る技術と支える技術 #osc19do
infinite_loop
 
PDF
Start rl with_unity_machine_learning_agents
infinite_loop
 
PDF
UniRx の1歩目
infinite_loop
 
PDF
がんばれ PHP Fiber
infinite_loop
 
PDF
心に残った名前ランキング
infinite_loop
 
PDF
プログラムと名前にまつわる座談会
infinite_loop
 
PDF
名は体を表していますか
infinite_loop
 
PDF
名前の力
infinite_loop
 
PDF
大切な名前[Intro]公開版
infinite_loop
 
PDF
JupyterNotebookとMySQLでゼロからはじめるデータサイエンス
infinite_loop
 
ChatGPT触ってみた
infinite_loop
 
社内ソフトスキルを考える
infinite_loop
 
3Dプリンタって いいね
infinite_loop
 
VRChatでお酒が注げる飲み物アセットの紹介
infinite_loop
 
アニメーションとスキニングをBurstで独自実装する.pdf
infinite_loop
 
I ❤ Virtual Machines 仮想環境をより便利に使うツールたち
infinite_loop
 
500万行のPHPプロジェクトにおけるログ出力の歩み
infinite_loop
 
ADRという考えを取り入れてみて
infinite_loop
 
リファクタリングで実装が○○分短縮した話
infinite_loop
 
ゲームのインフラをAwsで実戦tips全て見せます
infinite_loop
 
楽しいVR空間を作る技術と支える技術 #osc19do
infinite_loop
 
Start rl with_unity_machine_learning_agents
infinite_loop
 
UniRx の1歩目
infinite_loop
 
がんばれ PHP Fiber
infinite_loop
 
心に残った名前ランキング
infinite_loop
 
プログラムと名前にまつわる座談会
infinite_loop
 
名は体を表していますか
infinite_loop
 
名前の力
infinite_loop
 
大切な名前[Intro]公開版
infinite_loop
 
JupyterNotebookとMySQLでゼロからはじめるデータサイエンス
infinite_loop
 

Recently uploaded (10)

PDF
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
PDF
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
PDF
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
PDF
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
PDF
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
PDF
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
PDF
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
PDF
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
PDF
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
PDF
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 

ソーシャルゲーム案件におけるDB分割のPHP実装