revision-up-to: | 8961 (1.0) |
---|
Django は可能な限り全てのデータベースバックエンドをサポートしようとしていま すが、残念ながら全てのサーバが全く同じ仕様というわけではないので、どの機能 をサポートすべきか、どういった仕様を仮定するかといった設計上の判断を下して います。
このドキュメントでは、このドキュメントでは、 Django を使う上で関係のあるデー タベース機能について説明します。ただし、このドキュメントは特定のデータベー スサーバ向けのドキュメントとして書かれたものではなく、リファレンスマニュア ルでもありません。
Django はデータベースがトランザクションや参照の一貫性 (referential integrity)、 Unicode (UTF-8 エンコーディング) をサポートしていることを想定 して書かれています。好運なことに、 MySQL バージョン 3.23 以降でこれらの機 能全てをサポートしています。従って、 3.23 や 4.0 をバックエンドとして使うの は可能なのですが、 4.1 や 5.0 を使った方がトラブルに巻き込まれにくいでしょ う。
MySQL 4.1 では、文字セットのサポートを大幅に改良しています。 4.1 では、 データベース全体から、テーブル毎、カラム毎にいたるまで個別にデフォルトの文 字セットを指定できます。以前のバージョンでは、サーバ全体に対する文字セット の設定しかできませんでした。また、 4.1 になってはじめてオンザフライで文字セッ トを変更できるようになりました。 4.1 にはビューのサポートもありますが、 Django はまだこの機能をサポートしていません。
MySQL 5.0 では、全てのデータベーススキーマに関する詳細なデータの入った information_schema というデータベースが追加されました。 information_schema が存在すると、 Django はこのデータベースに対して inspectdb 機能を適用します。 5.0 ではまた、ストアドプロシジャのサポート も追加されましたが、 Django はまだこの機能をサポートしていません。
MySQL は複数の ストレージエンジン (以前はテーブルタイプ: table type と呼ばれていたもの) を選択できます。 デフォルトのストレージエンジンはサーバ設定で変更できます。
デフォルトのストレージエンジンは MyISAM です。 MyISAM の短所は、現状ではト ランザクションや外部キーをサポートしていないという点です。一方、 MyISAM は、 現状で、全文インデクスの生成や全文検索をサポートしている唯一のストレージエ ンジンです。
InnoDB エンジンは完全なトランザクション機能と外部キー参照をサポートしてい ます。
BDB エンジンは InnoDB と同様、完全なトランザクション機能を外部キー参照をサ ポートしていますが、やや時代送れになりつつあるようです。
SolidDB や Falcon といった その他のストレージエンジン まだまだ圏外の話です。現状では、おそらく InnoDB が最良の選択でしょう。
MySQLdb は Python から MySQL にアクセスするためのインタフェースです。 Django から利用できる MySQL の全ての機能を使うには、 バージョン 1.2.1p2 以 降が必要です。
Note
MySQLdb を Django から使おうとして ImportError: cannot import name ImmutableSet が出る場合は、おそらく MySQLdb に古い sets.py ファイルが入っていて、 Python 2.4 の同名の組 み込みモジュールと衝突しています。この問題を回避するには、 1.2.1p2 以降 の MySQLdb をインストールしてください。上書きインストールした場合には、 MySQLdb のインストールディレクトリを調べ、以前のバージョンの sets.py が入っていれば除去してください。
コマンドラインツールを使って、以下の SQL を発行すれば データベースを作成 できます:
CREATE DATABASE <dbname> CHARACTER SET utf8;
これで、全てのテーブルとカラムがデフォルトで UTF-8 を使うようになります。
カラムのコレーション設定は、データの保存方法や、文字列の等価性の定義を制御 しています。コレーションはデータベース全体でも、テーブル単位でも、カラム単 位でも設定できます。コレーションの詳細は MySQL のドキュメントで 詳しく解説されています 。いずれの場合でも、コレー ションの設定は直接データベーステーブルに対して行ってください。 Django はモ デル定義でコレーションを設定する方法を提供していません。
デフォルトの構成では、 MySQL は UTF-8 のデータベースに対して utf8_general_ci_swedish コレーションを使います。この設定では、全ての文 字列の等値比較が 大小文字を区別 せず行われます。つまり、 "Fred" と "freD" はデータベースレベルでは同じ値だとみなされるのです。そのため、デ フォルトのコレーションを使っていると、フィールドに unique 制約をかけた ときに、 "aa" と "AA" は等しいとみなされ (一意性が破れるので) 同じ カラムに入れられなくなります。
大抵のケースでは、デフォルトの設定はさして問題を起こしません。しかし、特定 のカラムやテーブルで大小文字を区別させたいなら、そのカラムやテーブルに utf8_bin コレーションを指定せねばなりません。その場合、注意すべきなのは、 MySQLdb 1.2.2 を使っていると、 Django のデータベースバックエンドが、データ ベースから取り出した文字列フィールドの値として (unicode 文字列ではなく) bytestring を返すということです。このふるまいは、 常に unicode を返す、と いう Django の通常のやりかたから大きくかけ離れています。コレーションを utf8_bin にして、 bytestring を受け取ったときの扱いは、開発者に委ねられ ています。 Django 自体はこのカラムを問題なく扱えますが、一貫性をもってデー タを処理したければ、 django.utils.encoding.smart_unicode() を何度も 呼び出すことになるでしょう。(データベースバックエンドレイヤとモデルの操作レ イヤは内部的に分離しているため、変換が必要かどうかをデータベースレイヤでは 判断できないので) Django はこの変換に関知しないのです。
MySQLdb 1.2.1p2 を使っているなら、コレーションを utf8_bin にしても、 CharField は unicode 文字列を返します。しかし、 今度は TextField が (Python 標準モジュール array の) array.array を返します。データをデータベースから読み出す ときに、変換に必要な情報が手にはいらないので、 Django 側ではどうしようもあ りません。 この問題は MySQLdb 1.2.2 で解決済み なので、 itf8_bin コレーションで TextField を使いたけ れば、バージョンを 1.2.2 に上げて、バイト文字列として扱うよう勧めます (それ ほど難しくはありません)。
MySQLdb 1.2.1p2 で utf8_bin コレーションの設定されたテーブルを使うのな ら、 django.contrib.sessions.models.Session のテーブル (通常は django_session) や、 django.contrib.admin.models.LogEntry のテーブル (通常は django_admin_log) のコレーションに utf8_collation_ci_swedish (デフォルトのコレーション) を使わねばなりませ ん。これらは標準の Django のテーブルのうち、内部的に TextField を使っているものだからです。
設定に関するドキュメント を参照してください。
接続に関する設定は、以下の順に適用されます:
別の言い方をするなら、 DATABASE_OPTIONS 内にデータベースの名前を 設定すると、その内容は DATABASE_NAME よりも優先順位が高くなり、 さらに DATABASE_NAME は MySQL のオプション設定ファイル の内容 をオーバライドするということです。
MySQL のオプション設定ファイルを使う例を以下に示します:
# settings.py
DATABASE_ENGINE = "mysql"
DATABASE_OPTIONS = {
'read_default_file': '/path/to/my.cnf',
}
# my.cnf
[client]
database = DATABASE_NAME
user = DATABASE_USER
password = DATABASE_PASSWORD
default-character-set = utf8
この他にも、MySQLdb の接続オプションには、 ssl, use_unicode, init_command, sql_mode といった便利なものがあります。詳しくは MySQLdb のドキュメント を参照してください。
Django はスキーマを作成する際にストレージエンジンを指定しません。そのため、 テーブルは常にサーバに設定されたデフォルトのストレージエンジンで作成されま す。作成されるテーブルを特定のタイプにしたければ、データベースサーバのデフォ ルトストレージエンジンを Django で使いたいストレージエンジンに合わせるのが 一番簡単です。
ホスティングサービスを使っていて、サーバのデフォルトのストレージエンジンを 変更できない場合、二つの選択肢があります。
テーブルが作成された後に、以下のようなクエリを発行して、ストレージ エンジンを (InnoDB) などに変更します:
ALTER TABLE <tablename> ENGINE=INNODB;
テーブルが沢山ある場合には、これは相当骨がおれることでしょう。
あるいは、テーブルを作成する前に、 MySQLdb の init_command オプショ ンを使います:
DATABASE_OPTIONS = { ... "init_command": "SET storage_engine=INNODB", ... }
このように設定しておくと、接続時にデフォルトのストレージエンジンが変更 されます。ただし、テーブルが全て作成され、運用環境で動き始めたら、この オプションを外しておかねばなりません。
syncdb 時にストレージエンジンを変更するもう一つの方法は、 Wiki の AlterModelOnSyncDB に記載されています。
MySQL には直接的な BOOLEAN カラム型がないので、 Django は BooleanField の値を TINYINT カラムを使って 0 または 1 で保存します。詳しくはモデルフィールドのドキュメントを参照してくだ さい。ただし、フィールドの値を出力したり、値が True や False でなけ ればならないような場合を除いて、特に問題はありません。
バージョン 3.3.5 以前の SQLite には、 ORDER_BY パラメタの扱いかたに バグがあります 。そのため、クエリセットメソッド extra() を使って select のパラメタを指定しようとすると問題を引き起 こします。このバグは、 OperationalError: ORDER BY terms must not be non-integer constants とい うメッセージを出力します。 SQLite のバージョンを 3.3.6 に上げ、 pysqlite2 モジュールを更新すれば、問題を解決できます。
バージョン 3.3.6 は 2006 年の 4 月にリリースされており、現在手に入る各プラッ トフォームのほとんどのバイナリ配布物で、Python から pysqlite2 や sqlite3 を介して使える SQLite は新しいバージョンなので、あまり大きなイ ンパクトはありません。
ただし、 Windows の場合、 Python 2.5 の公式の安定版リリースのバイナリ配布物 には (今のところ 2.5.2 も)、 SQLite 3.3.4 が組み込まれているため、バグが確 認されています。このため (Django 1.0 で) 3 つのテストスイートが失敗します。 この問題は、上で述べたように、 新しいバージョン SQLite が組み込まれた pysqlite2 (pysqlite-2.x.x.win32-py2.5.exe) をダウンロードしてインス トールすれば解決できます。 Python 2.6 には新たなバージョンの SQLite が付属 する予定なので、この問題の影響を受けないはずです。
上記のプラットフォームを使っていて、 pysqlite や SQLite を更新する必要 があるなら、Django のソースツリーの django/db/backends/sqlite3/base.py ファイルを手で編集して、 sqlite3 より pysqlite2 が先に import され るように変更してください。
Django はバージョン 9i 以降の Oracle データベースサーバ をサポートしてい ます。 Django の regex および iregex クエリオペレータを使うには、 バージョン 10g 以降の Oracle を使う必要があります。 バージョン 4.3.1 以降の cx_Oracle ドライバが必要です。
Oracle で python manage.py syncdb コマンドを動かすには、データベースユー ザに以下のコマンドを実行できる権限が必要です:
Django のテストスイートを実行させるには、 さらに 以下の権限が必要です:
Oracle を使う場合、 Django の settings.py は以下のように設定します:
DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = ''
DATABASE_PORT = ''
tnsnames.ora ファイルや、 SID として扱われる名前 (上の例では "xe") を使わない場合は、以下のように DATABASE_HOST および DATABASE_PORT を設定してください:
DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = 'dbprod01ned.mycompany.com'
DATABASE_PORT = '1540'
DATABASE_HOST と DATABASE_PORT は、両方とも指定するか、 両方とも空にするかどちらかにしてください。
Oracle ベースのシステムでパフォーマンス向上に使われているパラダイムとして、 「 テーブルスペース (tablespace)」によるディスクレイアウトの構築がありま す。 db_tablespace オプションを Meta と Field クラスに追加する と、 Oracle バックエンドはテーブルスペースを利用します (バックエンドがテー ブルスペースをサポートしなければ、 Django はこのオプションを無視します)。
モデルのテーブルにテーブルスペースを指定するには、モデルの内部クラス Meta に db_tablespace オプションを指定します。モデル全体とは別のテー ブルスペースをフィールドのカラムインデクスに指定したければ、フィールドのコ ンストラクタに db_tablespace を指定します。カラムごとにインデクスを生成 しない場合には、 db_tablespace オプションは無視されます:
class TablespaceExample(models.Model):
name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")
data = models.CharField(max_length=255, db_index=True)
edges = models.ManyToManyField(to="self", db_tablespace="indexes")
class Meta:
db_tablespace = "tables"
上の例では、 TablespaceExample モデルの生成するテーブル (モデルテーブルと多対多のリレーションのテーブル) は、 tables という名前 のテーブルスペースに保存されます。 name フィールドと、多対多リレーショ ンテーブルのインデクスは indexes テーブルスペースに保存されます。 data フィールドもインデクスを生成しますが、このインデクスのテーブルスペー スは指定されていないので、デフォルトの挙動としてテーブルスペース tables に保存されます。
db_tablespace オプションのデフォルト値を指定するには、 DEFAULT_TABLESPACE および DEFAULT_INDEX_TABLESPACE 設 定を使います。これらの設定は、組み込みの Django アプリケーションや、ソース コードをいじれないアプリケーションに対してテーブルスペースを指定する場合に 便利です。
Django 自体にはテーブルスペースを作成する機能はありません。 テーブルスペースの作成や管理の方法は、 Oracle のドキュメント を参照して ください。
Oracle は名前の長さを 30 文字以下に制限しています。この制限に合わせるために、 バックエンドは識別子名を切り詰めて、最後の 4 文字を MD5 のハッシュ値で置き 換えます。
Django は通常、 NULL ではなく空文字列を使うようにしていますが、 Oracle はこ れらを別々のものとして扱います。この問題を回避するには、 Oracle バックエン ドは空文字列を値として受け入れるフィールドに null=Ture オプションを 強制的に付加します。データベースから値を取り出すとき、フィールドの値が NULL であれば、そのフィールドの値は実際には空文字列であるとみなし、値も暗黙のう ちに空文字列に変換されます。
Oracle バックエンドは TextField を NCLOB カラム形式で保存します。 Oracle は、一般に LOB カラムに以下の制約を課しています:
Aug 31, 2012