DB:MySQL 5.5.20(WampServer、デフォルト構成)
OS:Win 7
HDD:Western Digital 3TB Caviar Green、3.5インチ、IntelliPower、64MB、Sata3(WD30EZRX)
メモリ:8 GB
MySQL my.ini: http://pastie.org/private/go9kaxlmlvirati2txbaa
問題のクエリ:
SELECT name.id AS name_id、name.name、cast_info.id、
cast_info.role_id、cast_info.movie_id
FROM cast_info
name.id = cast_info.person_id ON LEFT JOIN name
WHERE cast_info.movie_id = 1000000
ORDER BY cast_info.movie_id ASC
特定の映画に取り組んだすべての人を取得します。問題は、0.1秒から2.0秒近くまでかかる可能性があることです。長すぎます。ユーザーが1万回実行する必要がある場合、アプリケーションをアンインストールすることもできます。それが終わるのを待つ我慢もなかった。
編集:クエリの実行にかかる時間は、クエリに取り組んだ人の数によって決まります。 10人あたり約0.1秒。
説明:
*************************** 1.行******************** *******
id:1
select_type:SIMPLE
テーブル:cast_info
タイプ:参照
possible_keys:idx_mid、mpi
キー:idx_mid
key_len:4
ref:const
行:15
追加:
*************************** 2.行*************** ************
id:1
select_type:SIMPLE
テーブル:名前
タイプ:eq_ref
possible_keys:PRIMARY、id_name_idx
キー:プライマリ
key_len:4
参照:imdb.cast_info.person_id
行:1
追加:
テーブル:
テーブルの作成
cast_info
(id
int(11)NOT NULL AUTO_INCREMENT、person_id
int(11)NOT NULL、movie_id
int(11)NOT NULL、person_role_id
int(11)デフォルトのNULL、note
テキスト、nr_order
int(11)デフォルトのNULL、role_id
int(11)NOT NULL、
主キー(id
)、
キーidx_pid
(person_id
)、
キーidx_mid
(movie_id
)、
キーidx_cid
(person_role_id
)、
キーcast_info_role_id_exists
(role_id
)、
KEYmpi
(movie_id
、person_id
、id
)
)ENGINE = MyISAM AUTO_INCREMENT = 33261692 DEFAULT CHARSET = utf8CREATE TABLE
name
(id
int(11)NOT NULL AUTO_INCREMENT、name
varchar(110)NOT NULL、imdb_index
varchar(12)デフォルトのNULL、imdb_id
int(11)デフォルトのNULL、gender
varchar(1)DEFAULT NULL、name_pcode_cf
varchar(5)デフォルトのNULL、name_pcode_nf
varchar(5)デフォルトのNULL、surname_pcode
varchar(5)デフォルトのNULL、md5sum
varchar(32)デフォルトのNULL、
主キー(id
)、
キーidx_name
(name
(6))、
キーidx_imdb_id
(imdb_id
)、
キーidx_pcodecf
(name_pcode_cf
)、
キーidx_pcodenf
(name_pcode_nf
)、
キーidx_pcode
(surname_pcode
)、
キーidx_md5
(md5sum
)、
キーid_name_idx
(id
、name
)
)ENGINE = MyISAM AUTO_INCREMENT = 4287972 DEFAULT CHARSET = utf8
ありがとう!
編集:これは、1人のユーザーが1つのローカルアプリケーションで使用するローカルデータベースであるため、MyISAMが使用されます。同時に1つのクエリのみが実行されます。また、IMDbPyはInnoDBでデータベースを構築するのに少なくとも1か月かかるため...
編集:InnoDBに変換した後にEXPLAINをクエリします
*************************** 1.行******************** *******
id:1
select_type:SIMPLE
テーブル:cast_info
タイプ:参照
possible_keys:mpi
キー:mpi
key_len:3
ref:const
行:23
追加:
*************************** 2.行*************** ************
id:1
select_type:SIMPLE
テーブル:名前
タイプ:eq_ref
possible_keys:PRIMARY、id_name_idx
キー:プライマリ
key_len:4
参照:imdb.cast_info.person_id
行:1
追加:
InnoDBを使用するとより高速に実行され、
_PRIMARY KEY
_は「クラスター化」されています。これにより、name
への検索が速くなります。
たとえば、5G(8GBマシンの場合)の_innodb_buffer_pool_size
_を適切に設定すると、大量のデータがキャッシュされ、1万回の操作のI/Oが最小限になります。
また、必要に応じて_MEDIUMINT UNSIGNED
_または_SMALLINT UNSIGNED
_を使用して、データを縮小(およびI/Oを削減)することもできます。
削除できる(すべき)冗長なインデックスがあります。これはロードをスピードアップします。また、name(6)
はおそらく役に立たないでしょう。
クエリを見て、説明してから、テーブルの定義と最初の質問が頭に浮かびました。まだMyISAM @ 5.5を使用しているのはなぜですか?これをInnoDBに変更すると、結果が得られます。この0.1から2の範囲は、ロックまたはその他の理由が原因である可能性がありますが、最初にその問題を回避しましょう。
以下の変換ではテーブルがロックされ、ダウンタイムが発生する可能性があることに注意してください。
alter table cast_info engine=innodb;
alter table name engine=innodb;
パフォーマンスはハードドライブと一致しています。SSD、またはさらに優れたRAIDシステムを検討する必要があります。ドライブは低速なデスクトップクラスのハードドライバーであり、データベースの作業にはまったく適していません。 7200 rpmのデスクトップでテストしてみると、すでに改善が見られます。 Peopleテーブルが大きすぎてRAM(OSによってキャッシュされ、ユーザーメモリにロードされない))の場合、ハードドライブへの物理的な非順次アクセスがパフォーマンスの問題です。
「真の」データベースを実行しないが、デスクトップアプリケーションでデータを顧客に発送する場合、簡単な解決策は、必要なすべてのデータを使用して、映画の冗長フィールド「cast_data」を非正規化して追加することです。 JSONとして。このような構造の更新は、映画以外の方法(キャストの誕生日の更新など)で実行すると困難になりますが、データはストレージに関係なく非常に高速に取得されます。