データベースのサポート状況

revision-up-to:7127 (0.97pre SVN)

Django は可能な限り全てのデータベースバックエンドをサポートしようとしていま すが,残念ながら全てのサーバが全く同じ仕様というわけではないので,どの機能 をサポートすべきか,どういった仕様を仮定するかといった設計上の判断を下して います.

このドキュメントでは,このドキュメントでは, Django を使う上で関係のあるデー タベース機能について説明します.ただし,このドキュメントは特定のデータベー スサーバ向けのドキュメントとして書かれたものではなく,リファレンスマニュア ルでもありません.

MySQL に関する注意

Django はデータベースがトランザクションや参照の一貫性 (referential integrity), Unicode (UTF-8 エンコーディング) をサポートしていることを想定 して書かれています.好運なことに, MySQL バージョン 3.23 以降でこれらの機 能全てをサポートしています.従って, 3.23 や 4.0 をバックエンドとして使うの は可能なのですが, 4.1 や 5.0 を使った方がトラブルに巻き込まれにくいでしょ う.

MySQL 4.1

MySQL 4.1 では,文字セットのサポートを大幅に改良しています. 4.1 では, データベース全体から,テーブル毎,カラム毎にいたるまで個別にデフォルトの文 字セットを指定できます.以前のバージョンでは,サーバ全体に対する文字セット の設定しかできませんでした.また, 4.1 になってはじめてオンザフライで文字セッ トを変更できるようになりました. 4.1 にはビューのサポートもありますが, Django はまだこの機能をサポートしていません.

MySQL 5.0

MySQL 5.0 では,全てのデータベーススキーマに関する詳細なデータの入った information_schema というデータベースが追加されました. information_schema が存在すると, Django はこのデータベースに対して inspectdb 機能を適用します. 5.0 ではまた,ストアドプロシジャのサポート も追加されましたが, Django はまだこの機能をサポートしていません.

ストレージエンジン

MySQL は複数の ストレージエンジン (以前はテーブルタイプ: table type と呼ばれていたもの) を選択できます. デフォルトのストレージエンジンはサーバ設定で変更できます.

デフォルトのストレージエンジンは MyISAM です. MyISAM の短所は,現状ではト ランザクションや外部キーをサポートしていないという点です.一方, MyISAM は, 現状で,全文インデクスの生成や全文検索をサポートしている唯一のストレージエ ンジンです.

InnoDB エンジンは完全なトランザクション機能と外部キー参照をサポートしてい ます.

BDB エンジンは InnoDB と同様,完全なトランザクション機能を外部キー参照をサ ポートしていますが,やや時代送れになりつつあるようです.

SolidDBFalcon といった その他のストレージエンジン まだまだ圏外の話です.現状では,おそらく InnoDB が最良の選択でしょう.

MySQLdb

MySQLdb は Python から MySQL にアクセスするためのインタフェースです. Django から利用できる MySQL の全ての機能を使うには, バージョン 1.2.1p2 以 降が必要です.それ以前のバージョンは mysql バックエンドでは動作しません.

古いバージョンの MySQL と mysql_old バックエンドを使うつもりなら, おそらく 1.2.0 で動作するでしょう.

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 を使うようになります.

データベースに接続する

設定に関するドキュメント も参照してください.

接続に関する設定は,以下の順に適用されます:

  1. DATABASE_OPTIONS
  2. DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, DATABASE_HOST, DATABASE_PORT
  3. MySQL のオプション設定ファイル

別の言い方をするなら, DATABASE_OPTIONS 内にデータベースの名前を設定す ると,その内容は DATABASE_NAME よりも優先順位が高くなり,さらに DATABASE_NAMEMySQL のオプション設定ファイル の内容をオーバライドするということです.

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 に記載されています.

Oracle に関する注意

Django はバージョン 9i 以降の Oracle データベースサーバ をサポートしてい ます。 Django の regex および iregex クエリオペレータを使うには、 バージョン 10g 以降の Oracle を使う必要があります。 バージョン 4.3.1 以降の cx_Oracle ドライバが必要です。

Oracle で python manage.py syncdb コマンドを動かすには、データベースユー ザに以下のコマンドを実行できる権限が必要です:

  • CREATE TABLE
  • CREATE SEQUENCE
  • CREATE PROCEDURE
  • CREATE TRIGGER

Django のテストスイートを実行させるには、 さらに 以下の権限が必要です:

  • CREATE DATABASE
  • DROP DATABASE
  • CREATE TABLESPACE
  • DROP TABLESPACE

データベースへの接続

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_HOSTDATABASE_PORT は、両方とも指定するか、両方とも空に するかどちらかにしてください。

テーブルスペース

Oracle ベースのシステムでパフォーマンス向上に使われているパラダイムとして、 「 テーブルスペース (tablespace)」によるディスクレイアウトの構築がありま す。 db_tablespace オプションを MetaField クラスに追加する と、 Oracle バックエンドはテーブルスペースを利用します (バックエンドがテー ブルスペースをサポートしなければ、 Django はこのオプションを無視します)。

モデルのテーブルにテーブルスペースを指定するには、モデルの内部クラス Metadb_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 に保存されます。

開発版の Django で新たに登場した機能: db_tablespace オプションのデフォルト値を指定するには、 DEFAULT_TABLESPACE および DEFAULT_INDEX_TABLESPACE 設定を使います。 これらの設定は、組み込みの Django アプリケーションや、ソースコードをいじれ ないアプリケーションに対してテーブルスペースを指定する場合に便利です。

Django 自体にはテーブルスペースを作成する機能はありません。 テーブルスペースの作成や管理の方法は、 Oracle のドキュメント を参照して ください。

名前に関する制約

Oracle は名前の長さを 30 文字以下に制限しています。この制限に合わせるために、 バックエンドは識別子名を切り詰めて、最後の 4 文字を MD5 のハッシュ値で置き 換えます。

NULL 値よび空文字列

Django は通常、 NULL ではなく空文字列を使うようにしていますが、 Oracle はこ れらを別々のものとして扱います。この問題を回避するには、 Oracle バックエン ドは空文字列を値として受け入れるフィールドに null=Ture オプションを 強制的に付加します。データベースから値を取り出すとき、フィールドの値が NULL であれば、そのフィールドの値は実際には空文字列であるとみなし、値も暗黙のう ちに空文字列に変換されます。

TextField への制限

Oracle バックエンドは TextFieldNCLOB カラム形式で保存します。 Oracle は、一般に LOB カラムに以下の制約を課しています:

  • LOB カラムは主キーにできません。
  • LOB カラムはインデクス化に使えません。
  • LOB カラムは SELECT DISTINCT できません。従って、Oralce バックエン ドを使っていて、 TextField カラムを含むモデルに対して QuerySet.distinct を行うとエラーを引き起こします。このエラーを避け るには、 distinct() クエリの対象モデルから TextField を除去し、 TextField を持つ他のモデルを定義しておいてリレーションを張ってくだ さい。