2017-05-23 3 views
0

上の全表スキャンは、私は、次のMySQLのテーブル(のみ845行)を持っている:のMySQL - クエリを登録しよう

CREATE TABLE `categories_nested_set` (
    `lft` int(11) NOT NULL DEFAULT '0', 
    `rgt` int(11) DEFAULT NULL, 
    `id` int(11) DEFAULT NULL, 
    `category` varchar(128) DEFAULT NULL, 
    PRIMARY KEY (`lft`), 
    UNIQUE KEY `id` (`id`), 
    UNIQUE KEY `rgt` (`rgt`), 
    KEY `idx_lftrgtid` (`id`,`lft`,`rgt`), 
    KEY `idx_lft` (`lft`), 
    KEY `i1` (`lft`) USING BTREE, 
    KEY `i2` (`rgt`) USING BTREE, 
    KEY `i3` (`id`) USING BTREE, 
    CONSTRAINT `fk_categories_nested_set_id_category` FOREIGN KEY (`id`) REFERENCES `categories` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

(私は念のために、そこにインデックスの全体の多くを持って見ることができます)。

私は以下の自己結合クエリを実行します。以下は、EXPLAIN生成

SELECT * 
FROM categories_nested_set  AS H 
LEFT JOIN categories_nested_set AS I ON (H.lft > I.lft) 

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra 
1,SIMPLE,H,ALL,NULL,NULL,NULL,NULL,845,NULL 
1,SIMPLE,I,ALL,"PRIMARY,idx_lft,i1",NULL,NULL,NULL,845,"Range checked for each record (index map: 0x31)" 

enter image description here

をEXPLAINは、MySQLが使用しないように選択されていることを示唆していますインデックス、なぜ私は理解できません。表定義は、関連するすべての列が索引付けされることを示します。

これよりもはるかに大きなクエリ(500万行、14xテーブル)の範囲では、この部分は大きなボトルネックであることが判明しています。アドバイスをいただければ幸いです。

おかげで、

+0

'EXPLAIN'を実行したデータセットに実際には845行しかありませんか?例えば、データセットが十分に小さい場合、MySQLはインデックスを必ずしも使用しません。実際の大規模なクエリでパフォーマンス統計情報を取得する必要があります。 –

+0

はい、845行のみです。異なるものは大きなクエリで説明しますが、はるかに精巧ですが、それでもフルテーブルスキャンです。 – mils

+0

ジョインの左側にある表に対して、少なくとも1つのフル・テーブル・スキャンを実行する必要があります。 –

答えて

0

は、私はあなたがこのクエリを使用すべきだと思う:

SELECT * FROM categories_nested_set AS H , categories_nested_set AS I where (H.lft > I.lft); 

アイデアは、それが一度に1行を照合することによって、結果を構築するためにMySQLを強制するためにJOINを使用することではありません。

私が提案する解決策では、クロス積テーブルは結合なしで構築されるため、InnoDBは他のテーブルとは独立して最初のテーブル(H)から行をフェッチすることができます。 Hテーブルからのリンクが作成されていないため、2番目のテーブルのインデックスをMySQLで使用することができます。

私のコンピュータでは、提案されたソリューションは約5倍高速で、1000レコードのテーブルがあります。あなたも(それは必ずしもそうではありませんが)あなたが取得している列を制限することによって、あなたの要求のインデックスの使用を向上させることが

EXPLAIN SELECT * FROM categories_nested_set AS H , categories_nested_set AS I where (H.lft > I.lft); 

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE H ALL PRIMARY,idx_lft,i1 NULL NULL NULL 921 
1 SIMPLE I ALL PRIMARY,idx_lft,i1 NULL NULL NULL 921 Using where; Using join buffer 

注:ここでは

は説明の結果です。

+0

しかし、このクエリは多くの組み合わせを生成するので、好奇心によってのみ、このクエリでネストされたセットツリー構造から何を抽出しようとしますか?私が理解していることは、ノードのペアがすべて後になったときだが、私はあなたがそれで何をするのか分からない... –

+0

こんにちはアルノー、私はあなたの答えをまだ読んでいるが、あなたの質問、実際のクエリは、古典的なネストされたセットクエリです: ' LEFTは' ON I(I.lftとI.rgt BETWEEN H.lft)AS categories_nested_setを登録しよH ON H.id = C.id_category AS categories_nested_setを左結合私はBETWEEN – mils

+0

のパフォーマンスに関する混乱を取り除きたいと思います。同じ問題をここで実行しました: 'id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra 1、 SIMPLE、H、ALL、 "PRIMARY、idx_lft、i1"、NULL、NULL、NULL、845、NULL 1、SIMPLE、I、ALL、 "PRIM (レコード番号:0x31) " – mils

関連する問題