6

BLOB データを格納するテーブルへの外部キーを持つテーブルがあります。メイン テーブルの条件を使用してテーブルの内部結合を行うと、結合タイプが「インデックス」から「すべて」になります。私のブロブテーブルは数十ギガバイトのオーダーであるため、これを避けたいと思います。どうすれば回避できますか?

基本的な内部結合は次のとおりです。

EXPLAIN SELECT m.id, b.id, b.data 
        FROM metadata m, blobstore b 
        WHERE m.fkBlob = b.id;

1, 'SIMPLE', 'm', 'index', 'fk_blob', 'fk_blob', '4', '', 1, 'Using index'
1, 'SIMPLE', 'b', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'blob_index.m.fkBlob', 1, ''

ここでは、メイン テーブルに条件を追加します。

EXPLAIN SELECT m.id, b.id, b.data 
        FROM metadata m, blobstore b 
        WHERE m.fkBlob = b.id AND m.start < '2009-01-01';
1, 'SIMPLE', 'b', 'ALL', 'PRIMARY', '', '', '', 1, ''
1, 'SIMPLE', 'm', 'ref', 'fk_blob,index_start', 'fk_blob', '4', 'blob_index.b.id', 1, 'Using where'

テーブルがリストされている順序が変更されていることに注意してください。メイン テーブルに関して追加した条件のため、現在、BLOB テーブルでフル テーブル スキャンを実行しています。

スキーマは次のとおりです。

 DROP TABLE IF EXISTS `blob_index`.`metadata`;
    CREATE TABLE  `blob_index`.`metadata` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `fkBlob` int(10) unsigned NOT NULL,
      `start` datetime NOT NULL,
      PRIMARY KEY (`id`),
      KEY `fk_blob` (`fkBlob`),
      KEY `index_start` (`start`),
      CONSTRAINT `fk_blob` FOREIGN KEY (`fkBlob`) REFERENCES `blobstore` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


    DROP TABLE IF EXISTS `blob_index`.`blobstore`;
    CREATE TABLE  `blob_index`.`blobstore` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `data` mediumblob NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
4

5 に答える 5

3

空のテーブルでこれを試していると思います (MySQL は、完全なテーブル スキャンを実行するには 1 行を通過する必要があると考えているため)、スケジューラの結果に影響を与える可能性があります。実際のテーブルでそれを行うと、EXPLAIN結果が異なる場合があります (実際に私のテストでは異なりました)。

于 2009-12-23T12:48:21.317 に答える
0

あなたが投稿したものを正しく読むと、indexからrefeq_refに移動しallます。

CREATE INDEX idx_metadata USING BTREE ON `metadata` (fkBlob,start);

さっさと取り返せばいい。

于 2009-12-23T12:52:12.853 に答える
0

最初の例では、MySQL はメタデータ fk_blob インデックスを使用しました。これは、それがカバリング インデックスであったためです。クエリで使用したすべての列がインデックスに存在していました。(これが「インデックスを使用する」という意味です。) そのクエリは引き続きフル スキャンを実行しましたが、プライマリではなくセカンダリ インデックスを介してすべての行をスキャンしました。start を使用するとすぐに、カバリング インデックスが失われ、MySQL は blobstore を駆動インデックスとして使用する方が高速であると計算しました。(InnoDB のプライマリ インデックスは行ストレージと統合されています。)

MySQL で引き続きメタデータ インデックスを駆動インデックスとして使用する場合は、クエリに役立つ単一のインデックスがあることを確認してください。(start, fkBlob) のインデックスは 2 番目のクエリに最適ですが、他のクエリには役に立たない場合があります。次善のインデックスは、(fkBlob) を (fkBlob, start) に置き換えることです。インデックスが多すぎる (維持するのに費用がかかる) ことと、効率的なクエリ プランを持つことのバランスを取る必要があります。テスト、テスト、テスト - そして開発データベースの説明をやみくもに信じないでください。

于 2009-12-29T16:39:39.030 に答える
0
if the index doesnot take it right use HINTS

select /* INDEX <index_name> */
blah blah blah
from ........
于 2009-12-29T11:50:01.557 に答える