メリークリスマス!!今日はMySQL Casual Advent Calendar 2015の25日目をお届けするぞ!!
前回のエントリでは、MySQL 5.7におけるオプティマイザの改良点や新機能についてのスライドを紹介した。MySQL 5.7のオプティマイザの良し悪しは、ぜひみなさんの手で確かめて頂きたい。ところで、オプティマイザといえばひとつ前のバージョンである、MySQL 5.6で追加されたオプティマイザトレースという機能がとても便利だ。使いこなせばクエリチューニングの強い味方になるので、ぜひまだ使ったことがないという方は、一度試してみて欲しい。本ブログではまだ紹介していなかったので、今日はその使い方と見方を紹介しようと思う。

カスタム検索
2015-12-25
2010-10-05
知って得するInnoDBセカンダリインデックス活用術!
InnoDBはクラスタインデックスという構造になっている。今日はクラスタインデックスがどういうことかということを、皆さんに理解して頂きたい。もっとも理解して頂きたいポイントは「セカンダリインデックスのリーフノードには主キーの値が含まれている」ということだ。
2010-04-22
貧乏だってプロファイリングは出来る!! - poor man's profiler
従来より、プロファイリングのためのソフトウェアと言えば高価なものが中心であった。もっと安く、お金を掛けずに、簡単に、早くプログラムのボトルネックを探し出す方法はないのか?!ということで編み出されたプロファイリングテクノロジーがある。その名も、「poor man's profiler」だ。
2010-03-23
Not Only NoSQL!! 驚異的なまでにWRITE性能をスケールさせるSPIDERストレージエンジン
Webサービスでは、世界中からのトラフィックを捌く必要があるため、いくらチューニングしようとも一台のRDBMSでは捌ききることが出来ないのが常だ。MySQLは最初からマスター・スレーブ型のレプリケーション機能が搭載されており、スレーブをたくさんぶら下げることによって参照の負荷をスレーブに割り振るというスケールアウトによってその問題に対処してきた。スレーブによるスケールアウトは、参照(=PV)が多いWebサイトと非常に相性が良く、幾多のWebサイトにおいて実績を作ってきているし、まだまだ利用されている。
しかしながら、サイトのトラフィックが劇的に増加してくるようになると、レプリケーションによる負荷分散では追いつかなくなってきた。そこで人々がとった選択肢は、memcachedを利用することである。memcachedはインメモリ型の高速なKVSであり、参照・更新性能はMySQLより格段に高い。MySQLをバックエンドのストレージに利用し、なおかつmemcachedにホットなデータをキャッシュすることにより、データベースへの問い合わせを激減させることができるのである。
1:Nのレプリケーションでは、更新の負荷を分散することが出来ない。Webサイトの規模が大きくなると、更新の負荷も非常に高くなる。そこで次に用いられたのがShardingという技術である。Shardingとは、MySQLサーバーを複数用意し、アプリケーション側でデータを格納するべきサーバーを選択することである。
以上をまとめると、現在多くのWebサイトでは次のようなトポロジによって大規模なトラフィックを捌いている。
しかしながら、サイトのトラフィックが劇的に増加してくるようになると、レプリケーションによる負荷分散では追いつかなくなってきた。そこで人々がとった選択肢は、memcachedを利用することである。memcachedはインメモリ型の高速なKVSであり、参照・更新性能はMySQLより格段に高い。MySQLをバックエンドのストレージに利用し、なおかつmemcachedにホットなデータをキャッシュすることにより、データベースへの問い合わせを激減させることができるのである。
1:Nのレプリケーションでは、更新の負荷を分散することが出来ない。Webサイトの規模が大きくなると、更新の負荷も非常に高くなる。そこで次に用いられたのがShardingという技術である。Shardingとは、MySQLサーバーを複数用意し、アプリケーション側でデータを格納するべきサーバーを選択することである。
以上をまとめると、現在多くのWebサイトでは次のようなトポロジによって大規模なトラフィックを捌いている。
- レプリケーションによるスケールアウト
- memcachedによるデータベースへの問い合わせ抑制。
- Shardingによる更新の分散。
ラベル:
mysql,
performance tuning,
scaling,
spider,
storage engine
2010-03-17
たった3秒でInnoDBのデータローディングが快適になるライフハック
MySQLに限った話ではないが、データベース管理システムに大量のデータを投入するのは時間が掛かり大変苦痛を伴う作業である。劇的に効能があるわけではないが、MySQLを利用しているとき、特にInnoDBを使っている場合にはデータの投入を高速化するためにいくつかテクニックがあるので紹介しよう。皆さんの作業時間が短縮され、少しでも早く帰路に着いたりサービスインさせたりという形でお役に立てれば幸いである。ちなみに、タイトルはネタであるのだが、もし本当に3秒で以下の全ての設定を行えた人が居たら教えて頂きたい!
2010-01-05
違いが分かるエンジニアのためのMySQL/InnoDB/ZFSチューニング!
明けましておめでとうございます。今年もコンピューター道に邁進して参りますのでよろしくお願いします!
さて、今年一発目のネタはMySQL利用時におけるZFSのチューニングについて取り上げようと思う。Solarisに搭載されている機能の中でも最も注目度の高いものの一つであるZFSであるが、MySQLのバックエンドとしてはあまり利用されていないように思う。(そもそもSolarisのユーザー数自体がそれほど多くないという話もあるが。)ZFSは優れたファイルシステムであり、ファイルシステム自体にスナップショット機能が搭載されていたり容量の限界に先が見えない(充分すぎるほど余裕がある)といった管理上のメリットがあり、DBAにとっては垂涎のファイルシステムであると言える。(Linuxで利用出来ないのが難点だが、ZFSを使うためにSolarisを使うのもアリだろう。)
MySQL利用時におけるZFSのチューニングに関する日本語の記事は殆ど見かけない。しかし世界は広い。英語による記事ならば秀逸なものがある。そこで、今日は元サン・マイクロシステムズのパフォーマンス・エンジニアであるNeelakanth Nadgir氏によるZFSチューニングの解説記事を翻訳して紹介したいと思う。(翻訳することについては本人の了承済みである。氏は残念ながら昨年サンを去ってしまったが、翻訳を快諾してくれたことを感謝すると共に今後の活躍を祈りたい!)
原文:MySQL Innodb ZFS Best Practices
さて、今年一発目のネタはMySQL利用時におけるZFSのチューニングについて取り上げようと思う。Solarisに搭載されている機能の中でも最も注目度の高いものの一つであるZFSであるが、MySQLのバックエンドとしてはあまり利用されていないように思う。(そもそもSolarisのユーザー数自体がそれほど多くないという話もあるが。)ZFSは優れたファイルシステムであり、ファイルシステム自体にスナップショット機能が搭載されていたり容量の限界に先が見えない(充分すぎるほど余裕がある)といった管理上のメリットがあり、DBAにとっては垂涎のファイルシステムであると言える。(Linuxで利用出来ないのが難点だが、ZFSを使うためにSolarisを使うのもアリだろう。)
MySQL利用時におけるZFSのチューニングに関する日本語の記事は殆ど見かけない。しかし世界は広い。英語による記事ならば秀逸なものがある。そこで、今日は元サン・マイクロシステムズのパフォーマンス・エンジニアであるNeelakanth Nadgir氏によるZFSチューニングの解説記事を翻訳して紹介したいと思う。(翻訳することについては本人の了承済みである。氏は残念ながら昨年サンを去ってしまったが、翻訳を快諾してくれたことを感謝すると共に今後の活躍を祈りたい!)
原文:MySQL Innodb ZFS Best Practices
2009-11-04
MySQL Clusterが苦手とするJOINを如何にして克服するべきか。
シェアードナッシング型の負荷分散機能を持ち、なおかつ同期レプリケーションによるHA機能まで備えたMySQL Cluster最大の弱点といえば、JOINの遅さであろう。MySQL ClusterのJOINは偽りなく遅い。JOINを多用するアプリケーションでMySQL Clusterを利用するのはある意味マゾヒスティックな行為であると言えよう。何故MySQL ClusterはJOINが遅いのか?それはMySQL Clusterが分散データベースだからである。
ご存じの通り、MySQLにおけるJOINのアルゴリズムにはNested Loopしかない。他のストレージエンジンを利用していればそれでも十分実用に耐えうるぐらい高速なのだが、MySQL Clusterの場合はそうはいかない。JOINでは自ずとストレージエンジンからデータをフェッチする回数が増えるが、MySQL Clusterの場合レコードのフェッチはネットワークを経由しなければいけないのでここがボトルネックになってしまう。
例えば、2つのNDBストレージエンジン(MySQL Cluster)のテーブルをJOINする場合を考えよう。外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要があるとする。その場合、外部表から1回(1回のスキャンオペレーションでデータをフェッチできる)、内部表からM回のフェッチをしなければならない。1回のフェッチにつき、ネットワーク上をパケットが往復するわけであるから、InnoDBやMyISAMのように同一ホストから(特にメモリ上のキャッシュから)データをフェッチする場合と比べてJOINは不利なのである。
単純に「ネットワーク接続を高速化すればいいじゃないか。10GbEのNICを使えば?」などと思うかも知れない。それはある意味正しいが、正しいアプローチではないと思う。確かにJOINの性能は向上するのだが、10GbEとてレイテンシは無視できないので同一ホスト上のメモリからデータをフェッチする場合より遅いのは明らかである。
少し話はそれるが、何かを処理するユニットを増強して(もしくはたくさん並べて)何とかしてしまおうというのは、いかにもBruteなやり方である。確かにハードウェアの性能向上はBruteなやり方でも良いと思うし、Bruteなやり方で成功した事例もたくさんある。例えばグラフィックスチップにたくさんの演算回路(シェーダ)を組み込んだり、ハイエンドサーバにCPUを満載したり、安価なマシンを並べてスケールアウトしたり。しかし、Bruteなアプローチではシステムの性能の限界はハードウェアの性能の限界によって頭打ちしてしまうことになる。だが一方で、ソフトウェアの性能向上を考える場合には、同じ条件のハードウェアで如何に高速化するかということを検討しなければならないと思う。つまり、もっとSmartなやり方でないといけない。ハードウェアはBruteに。ソフトウェアはSmartに。それがシステムを高速化する際のコツだろう。
そんなわけで話は戻るが、つまり単純にネットワーク接続を高速化するのは、一定の効果は上がるがすぐに限界を迎えてしまう可能性が高いのである。
現時点でも実装可能かつスマートなアプローチは、レプリケーションを利用することである。Kaj Arno氏のエントリでも紹介されているが、MySQL Clusterから通常のMySQL Serverへのレプリケーションを行い、JOINを伴う複雑なSELECTに関してはスレーブで実行することにより、複雑なSELECTを高速化するというテクニックが存在する。(詳細はKaj氏のブログエントリの図を参照して頂きたい。)スレーブへのレプリケーションは非同期なので、厳密な最新のデータに対するクエリは実行出来ないが、厳密な最新のデータが必要ない場合この方法は大抵うまくいく。システムの構築がちょっと面倒臭くなる以外弊害もない。複雑なクエリは集計データなどに利用されることが多いので、適用出来るシーンも多いだろう。
この方法で気をつけるべきポイントは、replicate[-wild]-do-tableやreplicate[-wild]-ignore-tableオプションを利用して、複製するテーブルを限定することである。そうしないとndb_apply_statusテーブルへの更新が出来ないというエラーに見舞われてしまうことになる。MySQL Clusterテーブルを更新すると、バイナリログは自動的にmysql.ndb_apply_statusテーブルへの更新が含まれてしまう。このテーブルはNDBストレージエンジンで定義されているテーブルでMySQL Cluster同士のレプリケーションに利用されるのだが、MySQL Clusterから通常のMySQL Serverへレプリケーションする場合には不要などころかエラーの元凶になるだけなのできっちりとフィルタリングしておこう。例えば、worldデータベースに存在するテーブルだけを対象にしたい場合は、スレーブのmy.cnfに次のようにreplicate-wild-do-tableを使って記述するといいだろう。
MySQL ClusterのSQLノード上で新規にテーブルを作成する場合、つまりCREATE TABLE tbl(...) ENGINE NDB;とした場合に、スレーブ側ではデフォルトのストレージエンジンが使用されることになる点にも注意したい。(通常のMySQL ServerにはNDBストレージエンジンは含まれていないからだ。)--storage-engineオプションを好みのもの(InnoDB等)に設定しておこう。
将来的にはMySQL ClusterのJOIN性能は大幅に改善される予定である。まず、近い将来に搭載される機能として挙げられるのがBKA(Batched Key Access)というJOIN最適化手法である。この方法では、これまで1+M回必要だったデータのフェッチが、最も効率的な場合にはたったの2回にまで減少する。2つのNDBテーブルのJOINにおいて外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要がある場合、BKAの動作は次のようになる。
実装されるのはかなり先になるだろうが、MySQL ClusterのJOINを劇的に高速化することが出来ると予想される機能が実装される見込みである。それはDbspjと呼ばれる機能であり、言うなれば「分散JOIN」とでも呼ぶべきシロモノである。かなり貪欲な性能の追求である。MySQL Clusterは分散型のRDBMSであるから、JOINの処理も分散して行えば良いじゃないかと考えるのが人情というもであるが、一方でそのような機能を実装するのは難しいということもまた事実である。(従って現時点ではそのような機能は実装されていない。)しかし難しいというのを理由にして諦めないのが真の漢。MySQL Cluster開発チームはこの難題にチャレンジしており、既に初期段階のテスト結果が開発者Jonas Oreland氏のブログで公表されている。ぶっちゃけ通常のJOINと比べると格段に速い。MySQL Clusterの正式リリースに搭載されるのはずっと先になるだろうが、楽しみな機能の一つである。
ご存じの通り、MySQLにおけるJOINのアルゴリズムにはNested Loopしかない。他のストレージエンジンを利用していればそれでも十分実用に耐えうるぐらい高速なのだが、MySQL Clusterの場合はそうはいかない。JOINでは自ずとストレージエンジンからデータをフェッチする回数が増えるが、MySQL Clusterの場合レコードのフェッチはネットワークを経由しなければいけないのでここがボトルネックになってしまう。
例えば、2つのNDBストレージエンジン(MySQL Cluster)のテーブルをJOINする場合を考えよう。外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要があるとする。その場合、外部表から1回(1回のスキャンオペレーションでデータをフェッチできる)、内部表からM回のフェッチをしなければならない。1回のフェッチにつき、ネットワーク上をパケットが往復するわけであるから、InnoDBやMyISAMのように同一ホストから(特にメモリ上のキャッシュから)データをフェッチする場合と比べてJOINは不利なのである。
ではMySQL ClusterにおいてJOINを高速化するにはどうすればいいだろうか?
単純に「ネットワーク接続を高速化すればいいじゃないか。10GbEのNICを使えば?」などと思うかも知れない。それはある意味正しいが、正しいアプローチではないと思う。確かにJOINの性能は向上するのだが、10GbEとてレイテンシは無視できないので同一ホスト上のメモリからデータをフェッチする場合より遅いのは明らかである。
少し話はそれるが、何かを処理するユニットを増強して(もしくはたくさん並べて)何とかしてしまおうというのは、いかにもBruteなやり方である。確かにハードウェアの性能向上はBruteなやり方でも良いと思うし、Bruteなやり方で成功した事例もたくさんある。例えばグラフィックスチップにたくさんの演算回路(シェーダ)を組み込んだり、ハイエンドサーバにCPUを満載したり、安価なマシンを並べてスケールアウトしたり。しかし、Bruteなアプローチではシステムの性能の限界はハードウェアの性能の限界によって頭打ちしてしまうことになる。だが一方で、ソフトウェアの性能向上を考える場合には、同じ条件のハードウェアで如何に高速化するかということを検討しなければならないと思う。つまり、もっとSmartなやり方でないといけない。ハードウェアはBruteに。ソフトウェアはSmartに。それがシステムを高速化する際のコツだろう。
そんなわけで話は戻るが、つまり単純にネットワーク接続を高速化するのは、一定の効果は上がるがすぐに限界を迎えてしまう可能性が高いのである。
現時点でも実装可能かつスマートなアプローチは、レプリケーションを利用することである。Kaj Arno氏のエントリでも紹介されているが、MySQL Clusterから通常のMySQL Serverへのレプリケーションを行い、JOINを伴う複雑なSELECTに関してはスレーブで実行することにより、複雑なSELECTを高速化するというテクニックが存在する。(詳細はKaj氏のブログエントリの図を参照して頂きたい。)スレーブへのレプリケーションは非同期なので、厳密な最新のデータに対するクエリは実行出来ないが、厳密な最新のデータが必要ない場合この方法は大抵うまくいく。システムの構築がちょっと面倒臭くなる以外弊害もない。複雑なクエリは集計データなどに利用されることが多いので、適用出来るシーンも多いだろう。
この方法で気をつけるべきポイントは、replicate[-wild]-do-tableやreplicate[-wild]-ignore-tableオプションを利用して、複製するテーブルを限定することである。そうしないとndb_apply_statusテーブルへの更新が出来ないというエラーに見舞われてしまうことになる。MySQL Clusterテーブルを更新すると、バイナリログは自動的にmysql.ndb_apply_statusテーブルへの更新が含まれてしまう。このテーブルはNDBストレージエンジンで定義されているテーブルでMySQL Cluster同士のレプリケーションに利用されるのだが、MySQL Clusterから通常のMySQL Serverへレプリケーションする場合には不要などころかエラーの元凶になるだけなのできっちりとフィルタリングしておこう。例えば、worldデータベースに存在するテーブルだけを対象にしたい場合は、スレーブのmy.cnfに次のようにreplicate-wild-do-tableを使って記述するといいだろう。
[mysqld] replicate-wild-do-table=world.%
MySQL ClusterのSQLノード上で新規にテーブルを作成する場合、つまりCREATE TABLE tbl(...) ENGINE NDB;とした場合に、スレーブ側ではデフォルトのストレージエンジンが使用されることになる点にも注意したい。(通常のMySQL ServerにはNDBストレージエンジンは含まれていないからだ。)--storage-engineオプションを好みのもの(InnoDB等)に設定しておこう。
しかし、MySQL Clusterの開発者たちは、JOINが遅いという現状をいつまでも放置しておくつもりはない。
将来的にはMySQL ClusterのJOIN性能は大幅に改善される予定である。まず、近い将来に搭載される機能として挙げられるのがBKA(Batched Key Access)というJOIN最適化手法である。この方法では、これまで1+M回必要だったデータのフェッチが、最も効率的な場合にはたったの2回にまで減少する。2つのNDBテーブルのJOINにおいて外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要がある場合、BKAの動作は次のようになる。
- 外部表からM行フェッチ(一回のスキャン)
- JOINに利用するキーの値をリストアップする。
- リストアップされたキーをNDBストレージエンジンにPush-Downする。
- 内部表からN行フェッチ(一回のスキャン)
BKAブラボー!!と思うかも知れない。
しかし、そんなところで終わるようなMySQL Cluster開発チームではないのである!!
しかし、そんなところで終わるようなMySQL Cluster開発チームではないのである!!
実装されるのはかなり先になるだろうが、MySQL ClusterのJOINを劇的に高速化することが出来ると予想される機能が実装される見込みである。それはDbspjと呼ばれる機能であり、言うなれば「分散JOIN」とでも呼ぶべきシロモノである。かなり貪欲な性能の追求である。MySQL Clusterは分散型のRDBMSであるから、JOINの処理も分散して行えば良いじゃないかと考えるのが人情というもであるが、一方でそのような機能を実装するのは難しいということもまた事実である。(従って現時点ではそのような機能は実装されていない。)しかし難しいというのを理由にして諦めないのが真の漢。MySQL Cluster開発チームはこの難題にチャレンジしており、既に初期段階のテスト結果が開発者Jonas Oreland氏のブログで公表されている。ぶっちゃけ通常のJOINと比べると格段に速い。MySQL Clusterの正式リリースに搭載されるのはずっと先になるだろうが、楽しみな機能の一つである。
2009-05-19
限界までMySQLを使い尽くす!!
どこまで出来るか?!やれるところまでやってやるぜ!!と、威勢が良いのは若い間だけの話。オトナのオトコは、攻めるときはとことん攻めるが自らの限界もわきまえて賢く振る舞うのがスマートってものである。というわけで、今日はMySQLのいろいろな限界についてまとめてみる。皆さんも是非MySQLの限界を知り、MySQLをもっとスマートに使って頂きたい。
SQL文の最大長
MySQLサーバーが実行出来るSQL文の最大長は、max_allowed_packetシステム変数で表される。max_allowed_packetの最大値は1GBである。max_allowed_packetの値はセッションごとにも設定可能なので、デフォルトではそこそこの値(16MBなど)に設定しておいて、必要に応じて大きな対を使うと良いだろう。
データベースの個数
データベースオブジェクトの個数に制限はない。データベースオブジェクトは、MySQLのデータディレクトリ(datadir)のサブディレクトリとして格納される。(データベースの属性は、各サブディレクトリのdb.optというファイルに格納されている。)従って、データベースの個数は「datadirにいくつディレクトリを作成することができるか?」で決まり、これはOSそのものやファイルシステムから制限を受ける。ちなみにLinuxの場合、ext2/ext3の場合は32768個までであり、ext4ではその制限は撤廃される。Solarisの場合、UFSでは32768個の制限があり、ZFSにはそのような制限はない。
データベースあたりのテーブル数
テーブル数についても、データベースの場合と同じようにOSそのものやファイルシステムから制限を受ける。しかし、ファイル数はサブディレクトリ数と違って制限はほとんどない。ext2の場合でも130兆個以上である。しかし、実質的には一つのディレクトリにあまりに大量のファイルを作成すると、ファイル操作が遅くなってしまうので性能上の限界が自ずと生じる。だいたい1万ファイルぐらいまでが関の山である。MyISAMの場合、.frm、.MYI、.MYDという3つのファイルを作成するので、3000テーブル程度にとどめておくのがいいだろう。パーティショニングを利用する場合、.parというファイルと、さらにパーティションごとに.MYIおよび.MYDが作成されるので、使用するファイル数は格段に増える。(パーティション数x2+2)InnoDBの場合、デフォルトではデータベースディレクトリに作成されるのは.frmファイルだけである。innodb_files_per_tableオプションを使用すると、.ibdファイルも作成される。
MySQLサーバー全体でのテーブル数
これはストレージエンジンごとの制限による。MyISAMやInnoDBでは特に制限はない。例えばMyISAMの場合、データベースを1024個つくり、データベースごとに1024個のテーブルを作れば、トータルで100万個のテーブルを作成することが可能だ。(そんな使い方をする人は居ないだろうが。)他のストレージエンジンには制限が存在するものもある。例えばMySQL Clusterでは、MaxNoOfTablesというパラメーターで設定する。MaxNoOfTablesの最大値は1600。
テーブルごとのカラム数
MySQLの制限値は4096個までである。さらに、ストレージエンジンごとにそれより小さい制限があればそれに従う。InnoDBの場合は1000カラムまでで、MyISAMは特に制限はなく4096個というMySQL自体の制限が適用される。MySQL Clusterではカラムとインデックスを合わせて128個までという制限がある。
システム全体でのカラム数
こちらもストレージエンジンごとの制限が適用されるが、MyISAMやInnoDBには制限はない。
MySQL ClusterではMaxNoOfAttributesパラメーターで設定することができる。MaxNoOfAttributesの最大値は2^32であるが、システム全体で保持することができるオブジェクト(テーブル、カラム、インデックス、データベースすべてを含む)が20320個までという制限があり、そちらが適用されることになる。
テーブルごとのインデックス数
ストレージエンジンには最低16個以上のインデックスをサポートすることが定められているが、上限は定義されていない。従って、ストレージエンジンごとの制限がそのまま適用される。MyISAMは64個、InnoDBは上限なし、MySQL Clusterはカラムとインデックスを合わせて128個までである。
インデックス長
MySQL自体の制限値は3072バイト(1024 x 3)までである。それぞれストレージエンジンごとの制限が適用されるが、InnoDBは内部的には3500バイトまでサポートしているので、インデックス長の制限値は適用されない。MyISAMは1000バイトまでである。MySQL Clusterにはインデックス長の制限はない。4.1以前のバージョンのMySQLでは1024バイトまでという制限があるので注意しよう。
インデックスあたりのカラム数
マルチカラムインデックスを作る場合、インデックス長も気にしなければいけないが、カラム数にも制限が存在する。MyISAMの場合は16まで、InnoDBの場合は制限なし、MySQL Clusterは32までである。
行サイズ
MySQL自体の上限は、64KBまでである。ただし、これにはBLOB(およびTEXT)は含まれない。BLOBは他の領域に格納されるからだ。さらに、ストレージエンジンごとに制限が存在する場合がある。
InnoDBは、テーブルスペースのページサイズの約半分で、ページサイズのデフォルトは16KBなのでデフォルトの行サイズは約8KBである。ページサイズを変更するには、MySQLをソースからコンパイルして、さらにテーブルスペースとログファイルを再作成する必要がある。ページサイズの上限は64KBであるので、その場合の1行の最大サイズは32KBとなる。MySQL Clusterは1行あたり最大8KB。
テーブルあたりの行数
MySQL自体にはテーブルごとの行数の制限はない。ただし、PRIMARYやUNIQUEインデックスが格納できる行数には限界があるので、だいたいはそちらの制限を受けることになる。例えばPRIMARY KEYのデータ型がINTの場合は-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295までという値の範囲をとるので、4294967295行以上を格納することは出来ないわけである。
テーブルサイズ
こちらもMySQL自体には制限はない。
InnoDBの場合は、テーブルスペースの最大サイズである64TBが実質の上限となる。それ以前に、64TBのファイルを作成できる必要があるのだが、ext3などのファイルシステムでは、ファイルサイズの上限が2TBなので、それより大きなテーブルを作成したい場合には、テーブルスペースを複数のファイルで構成する必要がある。
MyISAMの場合も、.MYIまたは.MYDファイルがOSまたはファイルシステムがサポートしているファイルの最大サイズの制限を受ける。Linuxの場合、ext2/ext3では2TB、ext4では16TB、XFSでは8エクサバイトまでである。SolarisではUFSの場合1TB、ZFSの場合16エクサバイトである。ただし、MyISAMはファイルサイズの他に、内部で利用しているポインタサイズによってもテーブルサイズの制限を受ける。デフォルトでは256TBまで(ただし5.0.6以前は4GBまで)のテーブルが作成可能である。ポインタサイズはCREATE TABLE実行時にMAX_ROWSおよびAVG_ROW_LENGTHオプションで指定可能である。(MAX_ROWS x AVG_ROW_LENGTHが希望するテーブルサイズ程度になるようにする。)
MySQL Clusterの場合はDataMemoryやIndexMemoryのサイズ、およびディスク型テーブルの場合はテーブルスペースのサイズが上限となる。
テンポラリテーブルサイズ
テンポラリテーブルは、メモリベースのものとディスクベースのものが存在する。メモリベースのもののサイズが限界に達すると、MyISAMに変換される。変換の処理が結構重いので、変換があまり発生しないようにテンポラリテーブルのサイズやクエリをチューニングする必要がある。
メモリベースのテンポラリテーブルのサイズは、tmp_table_sizeおよびmax_heap_table_sizeオプションで設定することができる。ディスクベースのテンポラリテーブルは、tmpdirの領域を使い尽くすまで作成可能である。
CHARのサイズ
255文字まで。バイトではなく文字で計算するのがミソである。マルチバイト文字を使うと、1文字辺りの最大バイト数x255バイトになる。例えばUTF-8の場合、1文字あたり3バイトまで消費するのでCHAR(255)は765バイトとなるので注意しよう。MySQL 6.0では4バイトUTF-8がサポートされるので、CHAR(255)は1020バイトになる。
VARCHARのサイズ
65535文字までである。ただし、1文字の最大サイズは3バイトなので、65535文字だと軽く1行あたりの最大サイズの上限である64KBを超えてしまう。そのような場合、自動的に(MEDIUM)TEXTなどに変換される。また、スペック上はシングルバイトの文字コードだとVARCHAR(65535)まで作成できることになっているが、実際には65529〜65535バイトの場合はエラーになってしまう。その場合は代わりにTEXTを使おう。
BLOB/TEXTのサイズ
通常のBLOB(TEXT)は64KBまで、TINYBLOB、MEDIUMBLOB、LONGBLOBはそれぞれ256バイト、16MB、4GBまでである。こちらはCHAR/VARCHARとは違って文字数ではなくバイト数なので気をつけよう。
INTの最大値
-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295まで。(4バイトだから。)TINYINTは1バイトなので-127〜128、SMALLINTは2バイトだから-32768〜32767、MEDIUMINTは3バイトだから-8388608〜8388607、BIGINTは8バイトだから-9223372036854775808〜9223372036854775807。UNSIGNEDはそれぞれ、TINYINTが255まで、SMALLINTが65535、MEDIUMINTが16777215、BIGINTが18446744073709551615。
DECIMALの最大値
DECIMALは最大で65桁まで定義することが可能である。小数点以下の桁数は30桁まで。従って、全体で65桁で小数点以下がない場合、つまりDECIMAL(65)は-99999999999999999999999999999999999999999999999999999999999999999〜99999999999999999999999999999999999999999999999999999999999999999まで格納することが出来る。全体で65桁で小数点以下が30の場合、つまりDECIMAL(65,30)は-99999999999999999999999999999999999.999999999999999999999999999999〜99999999999999999999999999999999999.999999999999999999999999999999まで格納することが出来る。
必要に応じて桁数を割り当てよう。
DATETIMEとTIMESTAMPの最大値
DATETIMEは1000-01-01 00:00:00〜9999-12-31 23:59:59、1970-01-01 00:00:01〜2038-01-09 03:14:07(ただし時間帯はUTC)まで格納することが出来る。TIMESTAMPは2038年問題にぶち当たるわけである。
テーブルあたりのパーティション数
1024(サブパーティション含む)
カラム名、テーブル名、データベース名などの識別子
MySQL自体の制限値は64文字までである。寿限無寿限無・・・と長いテーブル名をつけてもOKであるが、一般的には短くてわかり易い名前をつけることが多いので、テーブル名の最大長が問題になることはないだろう。
ただしMySQL Clusterは、カラム・インデックス名は31文字まで、テーブル名とデータベース名は合わせて122文字までという制限がある。
ユーザー数
制限なし。何名でも登録可能。ただし権限テーブルはメモリ内にキャッシュされるので、あまりに多すぎるとメモリを消費しすぎることになるので注意が必要だ。
ユーザー名
16文字まで。
パスワード長
制限なし。パスワードは、内部的にはPASSWORD()関数によってハッシュ値が計算され格納されるだけである。ただし、mysqlコマンドを-pオプションつきで実行した場合などに表示されるパスワードの入力を求めるプロンプトに対しては、80文字までしか入力出来ないという制限があるので注意しよう。
パスワード長が長ければ長いほどセキュアなパスワードであると言えるが、あまりに長すぎると覚えにくいので気をつけよう。
同時接続数
max_connectionsパラメーターで調整可能。max_connectionsオプションの最大値は100000(MySQL 5.1.17以降)である。ただし、MySQLは一つのコネクションに対して一つのスレッドを作成する仕様になっている。そのため、OSが作成出来るスレッド数(プロセスあたり/システム全体)によって制限される。OSが作成することができるスレッド数は、システム起動時に自動的に調整されたり、スタック領域のサイズによって制限される場合が多い。各OSにおけるスレッド数の調整については、MySQL Practice Wikiにまとめてあるので参照して欲しい。
また、コネクションごとにOSがTCP/IPソケットを一つ作成するが、その度にファイルディスクリプタを一つ消費する。従って、一つのプロセスが同時に開くことができるファイル数にも制限を受けることになる。(下記、同時にオープンできるテーブル数参照)
同時実行クエリ数
制限なし。接続している全てのセッションがクエリを実行することができる。ただし、ロックの競合などが発生して待たされる場合が多々あるので、真に同時に(内部的に)実行されるクエリ数はもっと少ない。
また、ストレージエンジンには同時に実行出来るトランザクション数に限界があるので、そちらの制限に引っかかるだろう。InnoDBの場合は1023トランザクションまで、MySQL ClusterはMaxNoOfConcurrentTransactionsパラメーターで調整できる。MaxNoOfConcurrentTransactionsの最大値は2^32弱である。
同時にオープンできるテーブル数
MySQL自体には制限はなく、ストレージエンジンごとに制限が存在する。
MyISAMの場合、テーブルをセッションが開く度にファイルディスクリプタを消費する。.MYIは全てのセッションで共有されるが、.MYDはセッションごとに一つのファイルディスクリプタが必要になる。従って、多くのファイル、多くの接続を同時に使用する場合には、同時にオープンできるファイル数を増やさなければならない。同時にopenできるファイル数は、open_files_limitパラメーターで設定することができ、内部的にはsetrlimit(ulimitコマンド相当のシステムコール)で調整することができるが、カーネルがさらに上限値を持っていることが多い。Linuxの場合は、sys.fs.file-maxカーネルパラメーターで、Solarisの場合はrlim_fd_max、rlim_fd_curカーネルパラメーターで調整する。
InnoDBは、デフォルトではテーブルスペースを共有しているのでこのような制限はない。ただしinnodb_files_per_tableオプションを使用している場合は同様に一つのプロセスが開くことができるファイル数に制限を受けることになる。
JOINできるテーブル数
61
サブクエリのネスト数
31回まで。(最外部クエリを合わせると全体で32階層になる。)
テーブルに設定出来るトリガ数
それぞれBEFORE/AFTERとINSERT/UPDATE/DELETEの組み合わせで6つまで。同じ種類のトリガを重複して設定することは出来ない。
レプリケーションスレーブ数
スレーブ数はserver-idの制限を受ける。server-idは2^32-1=65535が最大値なので、65535個のスレーブを設置することが理論的には可能。ただし、スレーブはマスターへ接続する必要があるので、マスターにおいて同時接続数が先に限界を迎えるだろう。それ以前に、ネットワークポート数やネットワーク帯域数が先に限界を迎えることになるだろう。
バイナリログサイズ
max_binlog_sizeで調整可能。max_binlog_sizeの最大値は1GB。
バイナリログファイル数
2147483647まで。それ以上のバイナリログを作成することはできずにエラーになるが、ここまでバイナリログを作成しなければならない状況は滅多にないだろう。
利用可能CPU数
利用可能なCPUコア数/ソケット数などに制限はない。また、商用版のライセンス形態もCPU数ではなくサーバー単位である。ただし、CPUが利用可能なことといくつまでスケールするかは別の話。スケーラビリティを重視している人はMySQL 5.4を使おう。
同時に起動できるMySQLサーバーインスタンス数
データディレクトリやTCP/IPポート番号、UNIXソケット、PIDファイルなどの資源が被らなければいくつでも起動可能。ただし、OSが同時に起動出来るプロセス数や、同時に開くことができるファイル数、TCP/IPポート数などの制限を受ける。
利用可能メモリ量
MySQLはシングルプロセス/マルチスレッドのプログラムなので、32ビット版のOSの場合は2GB〜3GBの制限がある。いくらマシンに搭載しているメモリがそれより多くても関係ない。LinuxやSolarisでは3GBまで、Windowsの場合はデフォルトでは2GBまで利用可能である。ただし、Windowsの場合も/3GBスイッチを設定することで、一つのプロセスが3GBまで利用することが可能である。64ビット版のOSおよびMySQLを使えば、そのような制限はない。システムが搭載しているメモリを全て余すことなく使うことが出来るだろう。(ただしメモリを割り当てすぎてスワップが発生するのは禁物だ!!)
SQL文の最大長
MySQLサーバーが実行出来るSQL文の最大長は、max_allowed_packetシステム変数で表される。max_allowed_packetの最大値は1GBである。max_allowed_packetの値はセッションごとにも設定可能なので、デフォルトではそこそこの値(16MBなど)に設定しておいて、必要に応じて大きな対を使うと良いだろう。
データベースの個数
データベースオブジェクトの個数に制限はない。データベースオブジェクトは、MySQLのデータディレクトリ(datadir)のサブディレクトリとして格納される。(データベースの属性は、各サブディレクトリのdb.optというファイルに格納されている。)従って、データベースの個数は「datadirにいくつディレクトリを作成することができるか?」で決まり、これはOSそのものやファイルシステムから制限を受ける。ちなみにLinuxの場合、ext2/ext3の場合は32768個までであり、ext4ではその制限は撤廃される。Solarisの場合、UFSでは32768個の制限があり、ZFSにはそのような制限はない。
データベースあたりのテーブル数
テーブル数についても、データベースの場合と同じようにOSそのものやファイルシステムから制限を受ける。しかし、ファイル数はサブディレクトリ数と違って制限はほとんどない。ext2の場合でも130兆個以上である。しかし、実質的には一つのディレクトリにあまりに大量のファイルを作成すると、ファイル操作が遅くなってしまうので性能上の限界が自ずと生じる。だいたい1万ファイルぐらいまでが関の山である。MyISAMの場合、.frm、.MYI、.MYDという3つのファイルを作成するので、3000テーブル程度にとどめておくのがいいだろう。パーティショニングを利用する場合、.parというファイルと、さらにパーティションごとに.MYIおよび.MYDが作成されるので、使用するファイル数は格段に増える。(パーティション数x2+2)InnoDBの場合、デフォルトではデータベースディレクトリに作成されるのは.frmファイルだけである。innodb_files_per_tableオプションを使用すると、.ibdファイルも作成される。
MySQLサーバー全体でのテーブル数
これはストレージエンジンごとの制限による。MyISAMやInnoDBでは特に制限はない。例えばMyISAMの場合、データベースを1024個つくり、データベースごとに1024個のテーブルを作れば、トータルで100万個のテーブルを作成することが可能だ。(そんな使い方をする人は居ないだろうが。)他のストレージエンジンには制限が存在するものもある。例えばMySQL Clusterでは、MaxNoOfTablesというパラメーターで設定する。MaxNoOfTablesの最大値は1600。
テーブルごとのカラム数
MySQLの制限値は4096個までである。さらに、ストレージエンジンごとにそれより小さい制限があればそれに従う。InnoDBの場合は1000カラムまでで、MyISAMは特に制限はなく4096個というMySQL自体の制限が適用される。MySQL Clusterではカラムとインデックスを合わせて128個までという制限がある。
システム全体でのカラム数
こちらもストレージエンジンごとの制限が適用されるが、MyISAMやInnoDBには制限はない。
MySQL ClusterではMaxNoOfAttributesパラメーターで設定することができる。MaxNoOfAttributesの最大値は2^32であるが、システム全体で保持することができるオブジェクト(テーブル、カラム、インデックス、データベースすべてを含む)が20320個までという制限があり、そちらが適用されることになる。
テーブルごとのインデックス数
ストレージエンジンには最低16個以上のインデックスをサポートすることが定められているが、上限は定義されていない。従って、ストレージエンジンごとの制限がそのまま適用される。MyISAMは64個、InnoDBは上限なし、MySQL Clusterはカラムとインデックスを合わせて128個までである。
インデックス長
MySQL自体の制限値は3072バイト(1024 x 3)までである。それぞれストレージエンジンごとの制限が適用されるが、InnoDBは内部的には3500バイトまでサポートしているので、インデックス長の制限値は適用されない。MyISAMは1000バイトまでである。MySQL Clusterにはインデックス長の制限はない。4.1以前のバージョンのMySQLでは1024バイトまでという制限があるので注意しよう。
インデックスあたりのカラム数
マルチカラムインデックスを作る場合、インデックス長も気にしなければいけないが、カラム数にも制限が存在する。MyISAMの場合は16まで、InnoDBの場合は制限なし、MySQL Clusterは32までである。
行サイズ
MySQL自体の上限は、64KBまでである。ただし、これにはBLOB(およびTEXT)は含まれない。BLOBは他の領域に格納されるからだ。さらに、ストレージエンジンごとに制限が存在する場合がある。
InnoDBは、テーブルスペースのページサイズの約半分で、ページサイズのデフォルトは16KBなのでデフォルトの行サイズは約8KBである。ページサイズを変更するには、MySQLをソースからコンパイルして、さらにテーブルスペースとログファイルを再作成する必要がある。ページサイズの上限は64KBであるので、その場合の1行の最大サイズは32KBとなる。MySQL Clusterは1行あたり最大8KB。
テーブルあたりの行数
MySQL自体にはテーブルごとの行数の制限はない。ただし、PRIMARYやUNIQUEインデックスが格納できる行数には限界があるので、だいたいはそちらの制限を受けることになる。例えばPRIMARY KEYのデータ型がINTの場合は-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295までという値の範囲をとるので、4294967295行以上を格納することは出来ないわけである。
テーブルサイズ
こちらもMySQL自体には制限はない。
InnoDBの場合は、テーブルスペースの最大サイズである64TBが実質の上限となる。それ以前に、64TBのファイルを作成できる必要があるのだが、ext3などのファイルシステムでは、ファイルサイズの上限が2TBなので、それより大きなテーブルを作成したい場合には、テーブルスペースを複数のファイルで構成する必要がある。
MyISAMの場合も、.MYIまたは.MYDファイルがOSまたはファイルシステムがサポートしているファイルの最大サイズの制限を受ける。Linuxの場合、ext2/ext3では2TB、ext4では16TB、XFSでは8エクサバイトまでである。SolarisではUFSの場合1TB、ZFSの場合16エクサバイトである。ただし、MyISAMはファイルサイズの他に、内部で利用しているポインタサイズによってもテーブルサイズの制限を受ける。デフォルトでは256TBまで(ただし5.0.6以前は4GBまで)のテーブルが作成可能である。ポインタサイズはCREATE TABLE実行時にMAX_ROWSおよびAVG_ROW_LENGTHオプションで指定可能である。(MAX_ROWS x AVG_ROW_LENGTHが希望するテーブルサイズ程度になるようにする。)
MySQL Clusterの場合はDataMemoryやIndexMemoryのサイズ、およびディスク型テーブルの場合はテーブルスペースのサイズが上限となる。
テンポラリテーブルサイズ
テンポラリテーブルは、メモリベースのものとディスクベースのものが存在する。メモリベースのもののサイズが限界に達すると、MyISAMに変換される。変換の処理が結構重いので、変換があまり発生しないようにテンポラリテーブルのサイズやクエリをチューニングする必要がある。
メモリベースのテンポラリテーブルのサイズは、tmp_table_sizeおよびmax_heap_table_sizeオプションで設定することができる。ディスクベースのテンポラリテーブルは、tmpdirの領域を使い尽くすまで作成可能である。
CHARのサイズ
255文字まで。バイトではなく文字で計算するのがミソである。マルチバイト文字を使うと、1文字辺りの最大バイト数x255バイトになる。例えばUTF-8の場合、1文字あたり3バイトまで消費するのでCHAR(255)は765バイトとなるので注意しよう。MySQL 6.0では4バイトUTF-8がサポートされるので、CHAR(255)は1020バイトになる。
VARCHARのサイズ
65535文字までである。ただし、1文字の最大サイズは3バイトなので、65535文字だと軽く1行あたりの最大サイズの上限である64KBを超えてしまう。そのような場合、自動的に(MEDIUM)TEXTなどに変換される。また、スペック上はシングルバイトの文字コードだとVARCHAR(65535)まで作成できることになっているが、実際には65529〜65535バイトの場合はエラーになってしまう。その場合は代わりにTEXTを使おう。
BLOB/TEXTのサイズ
通常のBLOB(TEXT)は64KBまで、TINYBLOB、MEDIUMBLOB、LONGBLOBはそれぞれ256バイト、16MB、4GBまでである。こちらはCHAR/VARCHARとは違って文字数ではなくバイト数なので気をつけよう。
INTの最大値
-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295まで。(4バイトだから。)TINYINTは1バイトなので-127〜128、SMALLINTは2バイトだから-32768〜32767、MEDIUMINTは3バイトだから-8388608〜8388607、BIGINTは8バイトだから-9223372036854775808〜9223372036854775807。UNSIGNEDはそれぞれ、TINYINTが255まで、SMALLINTが65535、MEDIUMINTが16777215、BIGINTが18446744073709551615。
DECIMALの最大値
DECIMALは最大で65桁まで定義することが可能である。小数点以下の桁数は30桁まで。従って、全体で65桁で小数点以下がない場合、つまりDECIMAL(65)は-99999999999999999999999999999999999999999999999999999999999999999〜99999999999999999999999999999999999999999999999999999999999999999まで格納することが出来る。全体で65桁で小数点以下が30の場合、つまりDECIMAL(65,30)は-99999999999999999999999999999999999.999999999999999999999999999999〜99999999999999999999999999999999999.999999999999999999999999999999まで格納することが出来る。
必要に応じて桁数を割り当てよう。
DATETIMEとTIMESTAMPの最大値
DATETIMEは1000-01-01 00:00:00〜9999-12-31 23:59:59、1970-01-01 00:00:01〜2038-01-09 03:14:07(ただし時間帯はUTC)まで格納することが出来る。TIMESTAMPは2038年問題にぶち当たるわけである。
テーブルあたりのパーティション数
1024(サブパーティション含む)
カラム名、テーブル名、データベース名などの識別子
MySQL自体の制限値は64文字までである。寿限無寿限無・・・と長いテーブル名をつけてもOKであるが、一般的には短くてわかり易い名前をつけることが多いので、テーブル名の最大長が問題になることはないだろう。
ただしMySQL Clusterは、カラム・インデックス名は31文字まで、テーブル名とデータベース名は合わせて122文字までという制限がある。
ユーザー数
制限なし。何名でも登録可能。ただし権限テーブルはメモリ内にキャッシュされるので、あまりに多すぎるとメモリを消費しすぎることになるので注意が必要だ。
ユーザー名
16文字まで。
パスワード長
制限なし。パスワードは、内部的にはPASSWORD()関数によってハッシュ値が計算され格納されるだけである。ただし、mysqlコマンドを-pオプションつきで実行した場合などに表示されるパスワードの入力を求めるプロンプトに対しては、80文字までしか入力出来ないという制限があるので注意しよう。
shell> mysql -uroot -p
Enter password: ←コレは80文字まで
パスワード長が長ければ長いほどセキュアなパスワードであると言えるが、あまりに長すぎると覚えにくいので気をつけよう。
同時接続数
max_connectionsパラメーターで調整可能。max_connectionsオプションの最大値は100000(MySQL 5.1.17以降)である。ただし、MySQLは一つのコネクションに対して一つのスレッドを作成する仕様になっている。そのため、OSが作成出来るスレッド数(プロセスあたり/システム全体)によって制限される。OSが作成することができるスレッド数は、システム起動時に自動的に調整されたり、スタック領域のサイズによって制限される場合が多い。各OSにおけるスレッド数の調整については、MySQL Practice Wikiにまとめてあるので参照して欲しい。
また、コネクションごとにOSがTCP/IPソケットを一つ作成するが、その度にファイルディスクリプタを一つ消費する。従って、一つのプロセスが同時に開くことができるファイル数にも制限を受けることになる。(下記、同時にオープンできるテーブル数参照)
同時実行クエリ数
制限なし。接続している全てのセッションがクエリを実行することができる。ただし、ロックの競合などが発生して待たされる場合が多々あるので、真に同時に(内部的に)実行されるクエリ数はもっと少ない。
また、ストレージエンジンには同時に実行出来るトランザクション数に限界があるので、そちらの制限に引っかかるだろう。InnoDBの場合は1023トランザクションまで、MySQL ClusterはMaxNoOfConcurrentTransactionsパラメーターで調整できる。MaxNoOfConcurrentTransactionsの最大値は2^32弱である。
同時にオープンできるテーブル数
MySQL自体には制限はなく、ストレージエンジンごとに制限が存在する。
MyISAMの場合、テーブルをセッションが開く度にファイルディスクリプタを消費する。.MYIは全てのセッションで共有されるが、.MYDはセッションごとに一つのファイルディスクリプタが必要になる。従って、多くのファイル、多くの接続を同時に使用する場合には、同時にオープンできるファイル数を増やさなければならない。同時にopenできるファイル数は、open_files_limitパラメーターで設定することができ、内部的にはsetrlimit(ulimitコマンド相当のシステムコール)で調整することができるが、カーネルがさらに上限値を持っていることが多い。Linuxの場合は、sys.fs.file-maxカーネルパラメーターで、Solarisの場合はrlim_fd_max、rlim_fd_curカーネルパラメーターで調整する。
InnoDBは、デフォルトではテーブルスペースを共有しているのでこのような制限はない。ただしinnodb_files_per_tableオプションを使用している場合は同様に一つのプロセスが開くことができるファイル数に制限を受けることになる。
JOINできるテーブル数
61
サブクエリのネスト数
31回まで。(最外部クエリを合わせると全体で32階層になる。)
テーブルに設定出来るトリガ数
それぞれBEFORE/AFTERとINSERT/UPDATE/DELETEの組み合わせで6つまで。同じ種類のトリガを重複して設定することは出来ない。
レプリケーションスレーブ数
スレーブ数はserver-idの制限を受ける。server-idは2^32-1=65535が最大値なので、65535個のスレーブを設置することが理論的には可能。ただし、スレーブはマスターへ接続する必要があるので、マスターにおいて同時接続数が先に限界を迎えるだろう。それ以前に、ネットワークポート数やネットワーク帯域数が先に限界を迎えることになるだろう。
バイナリログサイズ
max_binlog_sizeで調整可能。max_binlog_sizeの最大値は1GB。
バイナリログファイル数
2147483647まで。それ以上のバイナリログを作成することはできずにエラーになるが、ここまでバイナリログを作成しなければならない状況は滅多にないだろう。
利用可能CPU数
利用可能なCPUコア数/ソケット数などに制限はない。また、商用版のライセンス形態もCPU数ではなくサーバー単位である。ただし、CPUが利用可能なことといくつまでスケールするかは別の話。スケーラビリティを重視している人はMySQL 5.4を使おう。
同時に起動できるMySQLサーバーインスタンス数
データディレクトリやTCP/IPポート番号、UNIXソケット、PIDファイルなどの資源が被らなければいくつでも起動可能。ただし、OSが同時に起動出来るプロセス数や、同時に開くことができるファイル数、TCP/IPポート数などの制限を受ける。
利用可能メモリ量
MySQLはシングルプロセス/マルチスレッドのプログラムなので、32ビット版のOSの場合は2GB〜3GBの制限がある。いくらマシンに搭載しているメモリがそれより多くても関係ない。LinuxやSolarisでは3GBまで、Windowsの場合はデフォルトでは2GBまで利用可能である。ただし、Windowsの場合も/3GBスイッチを設定することで、一つのプロセスが3GBまで利用することが可能である。64ビット版のOSおよびMySQLを使えば、そのような制限はない。システムが搭載しているメモリを全て余すことなく使うことが出来るだろう。(ただしメモリを割り当てすぎてスワップが発生するのは禁物だ!!)
2009-04-17
パーティショニングの使用例 - http session情報
今日もパーティショニングの話の続きである。
パーティショニングが非常にフィットする(たぶん昨日の例よりも)もう一つのケースは、数日間だけ必要なデータを蓄えておくような場合だ。例えば、HTTPセッションやログ情報などが良い例ではないだろうか。そういう場合には、日付を使ってRANGEパーティショニングをするのである。RANGEパーティショニングでももちろんPruningによって性能の向上は出来るのだが、それよりも何よりも高速に不要なパーティションを破棄できるというのが大きい。パーティションの破棄は、内部的にはテーブルのDROPとほぼ同じ扱いなのである。DROPのスピードはストレージエンジンによるが、InnoDBやMyISAM、NDB(MySQL Cluster)ならばいくらデータを含んでいても関係なくDROPは一瞬である。テーブルから大量の行を削除すると、フラグメンテーションが発生したり、インデックスの統計情報が乱れてしまったりするのだが、パーティションごと削除してしまえばそのような心配は一切ないのでお勧めである。
パーティショニングが非常にフィットする(たぶん昨日の例よりも)もう一つのケースは、数日間だけ必要なデータを蓄えておくような場合だ。例えば、HTTPセッションやログ情報などが良い例ではないだろうか。そういう場合には、日付を使ってRANGEパーティショニングをするのである。RANGEパーティショニングでももちろんPruningによって性能の向上は出来るのだが、それよりも何よりも高速に不要なパーティションを破棄できるというのが大きい。パーティションの破棄は、内部的にはテーブルのDROPとほぼ同じ扱いなのである。DROPのスピードはストレージエンジンによるが、InnoDBやMyISAM、NDB(MySQL Cluster)ならばいくらデータを含んでいても関係なくDROPは一瞬である。テーブルから大量の行を削除すると、フラグメンテーションが発生したり、インデックスの統計情報が乱れてしまったりするのだが、パーティションごと削除してしまえばそのような心配は一切ないのでお勧めである。
2009-04-16
パーティショニングの使用例 - カーディナリティが低いカラムを使って検索する場合
MySQL 5.1で追加された機能にパーティショニングがある。これは適切に利用すれば非常に強力な機能であることは間違いないのだが、使いどころが難しい。なぜなら、
そんなわけで、今日と明日でパーティショニングが役に立つシーンを2つ紹介しようと思う。
- インデックスをつけるだけでカバー出来る場合が多い。
- パーショニングを使わずに、単にテーブルを分けてしまえばいい。
- テーブルが巨大にならないとあまり効果を実感できない。
- 使い方を間違えると性能が落ちてしまう。
そんなわけで、今日と明日でパーティショニングが役に立つシーンを2つ紹介しようと思う。
2009-04-07
2009-04-06
Distribution Awareness - MySQL Clusterにおけるスキーマチューニングの定石
MySQL Clusterはデータノードが増えると性能が低下する???
そのような噂を聞いたことがないだろうか。この噂は事実を含んでいる面もあるが、殆どの場合は適切にスキーマを設計していないことが原因で起きる。実はMySQL Clusterはその性能を遺憾なく発揮するためにはスキーマの設計が非常に大事なのである。
MySQL Clusterは複数のデータノード(ノードグループ)に対して主キーの値に基づいて行単位で分散されている。主キーに偏りがなければ各データノードに格納される行数は均等になる。つまり、MySQL ClusterはSharding(アプリケーションパーティショニング/Level2分散)を自ら行っていると言えるだろう。
そのような噂を聞いたことがないだろうか。この噂は事実を含んでいる面もあるが、殆どの場合は適切にスキーマを設計していないことが原因で起きる。実はMySQL Clusterはその性能を遺憾なく発揮するためにはスキーマの設計が非常に大事なのである。
MySQL Clusterは複数のデータノード(ノードグループ)に対して主キーの値に基づいて行単位で分散されている。主キーに偏りがなければ各データノードに格納される行数は均等になる。つまり、MySQL ClusterはSharding(アプリケーションパーティショニング/Level2分散)を自ら行っていると言えるだろう。
ラベル:
mysql,
mysql cluster,
performance tuning,
scaling,
sharding
2009-03-31
MySQLのEXPLAINを徹底解説!!
以前、MySQLを高速化する10の方法という投稿で「EXPLAINの見方についてはいずれ解説しようと思う」と書いてしまったので、今日はその公約?を果たそうと思う。
2009-03-25
なぜMySQLのサブクエリは遅いのか。
よくMySQLはサブクエリが弱いと言われるが、これは本当だろうか?半分は本当で半分は嘘である。MySQLのサブクエリだってなんでもかんでも遅いわけではない。落とし穴をしっかり避け、使いどころを間違えなければサブクエリも高速に実行できるのである。今日はMySQLがどんな風にサブクエリを実行し、どのような場合に遅いのかということについて説明しよう。
EXPLAINで実行計画を調べた際に、select_typeにはクエリの種類が表示されるのだが、代表的なサブクエリには次の3つのパターンがある。
EXPLAINで実行計画を調べた際に、select_typeにはクエリの種類が表示されるのだが、代表的なサブクエリには次の3つのパターンがある。
2009-03-18
Using filesort
去年ソートに関する記事を書いたが、今日はその続きである。
MySQLでEXPLAIN SELECT...を実行するとExtraフィールドでよく見かける「Using filesort」という文字列。Filesortって一体なんだろう?と思ったことはないだろうか。単刀直入に言ってFilesortの正体はクイックソートである。
MySQLでEXPLAIN SELECT...を実行するとExtraフィールドでよく見かける「Using filesort」という文字列。Filesortって一体なんだろう?と思ったことはないだろうか。単刀直入に言ってFilesortの正体はクイックソートである。
2009-03-04
さらにMySQLを高速化する7つの方法
MySQLを高速化する10の方法という記事がとても好評だったようである。記事を読んで頂いた皆さん、ありがとう。
この記事に対する便乗(?)でWeb屋のネタ帳: PostgreSQLを高速化する16のポイントという記事を書いて頂いたようだが、そちらの方もかなり人気だったようである。他人が作ったソフトウェアに改良を加えるというフリーソフトウェアやオープンソースソフトウェアの精神も基本は便乗であるので、便乗については大いに賛成したいというかむしろ取り上げてくれてありがとう!!と思うわけであるが、ここでさらに俺はこう考える。
と。
この記事に対する便乗(?)でWeb屋のネタ帳: PostgreSQLを高速化する16のポイントという記事を書いて頂いたようだが、そちらの方もかなり人気だったようである。他人が作ったソフトウェアに改良を加えるというフリーソフトウェアやオープンソースソフトウェアの精神も基本は便乗であるので、便乗については大いに賛成したいというかむしろ取り上げてくれてありがとう!!と思うわけであるが、ここでさらに俺はこう考える。
さらに自分も便乗するしかない!!
と。
2009-02-18
MySQLを高速化する10の方法
ちょっとキャッチ−なタイトルをつけてしまったが、今日は独断と偏見でMySQLを高速化する方法を10個紹介しよう。MySQLサーバをチューニングするときや初期導入する場合などに参考にしてもらいたい。
2009-02-03
プロファイリングで快適MySQLチューニング生活
MySQL 5.1からデフォルトで有効になっている便利な機能としてプロファイリングというものがある。MySQL 5.0でも利用出来たのだが、実験的な機能という位置づけであり、搭載されていたのはGPL版のMySQL Community Server限定だった。MySQL 5.1からは全てのエディションでプロファイリングを利用することができる。
プロファイリング機能を利用すると、クエリの状態(特に状態遷移やリソースの消費状況)を詳細に分析できるのでとても便利だ。MySQLエンジニア必携の機能といって良いだろう。というわけでプロファイリング機能の使い方を説明しよう。
プロファイリング機能を利用すると、クエリの状態(特に状態遷移やリソースの消費状況)を詳細に分析できるのでとても便利だ。MySQLエンジニア必携の機能といって良いだろう。というわけでプロファイリング機能の使い方を説明しよう。
2009-01-10
InnoDBのログとテーブルスペースの関係
InnoDBのデータ領域はログファイルとテーブルスペースという、切っても切れない2種類のファイルから構成されている。ログファイルは名前からするとただのログだから削除しても平気かな?と思って削除してしまうという問題が後を絶たない。そこで、今日はログファイルとテーブルスペースの関係について説明しようと思う。
2009-01-08
MySQL6.0における新しいJOIN最適化手法 - BKA
MySQL 6.0では新たなJOIN最適化手法であるBKA - Batched Key Accessの実装が進んでいる。BKAとは、読んで字のごとくキーを用いたアクセスをバッチ(ひとまとまりの)処理にすることである。
登録:
投稿 (Atom)