3

この単純なMySQLクエリを高速化する複合インデックスと、その複合インデックスを作成するにはどうすればよいですか?

SELECT * 
FROM  `Table1` 
WHERE  `col1` =  '145307'
AND  `col2` =  '0'
AND col3 NOT 
IN ( 130209, 130839 ) 
ORDER BY col4 DESC 
LIMIT 0 , 5

col1上記( 〜 )の各列には、すでに個別のインデックスがありますcol4


編集

の結果SHOW CREATE TABLE

CREATE TABLE `Table1` (  
 `primaryCol` int(11) NOT NULL AUTO_INCREMENT,
 `col3` int(11) DEFAULT '0',
 `col5` varchar(20) COLLATE utf8_bin DEFAULT NULL,
 `col1` int(11) DEFAULT '0',
 `col6` varchar(80) COLLATE utf8_bin DEFAULT NULL,
 `col7` text CHARACTER SET utf8,
 `col4` int(11) DEFAULT '0',
 `col8` char(1) COLLATE utf8_bin DEFAULT 'N',
 `col9` char(1) COLLATE utf8_bin DEFAULT 'N',
 `col2` tinyint(1) NOT NULL,
 `col10` tinyint(1) NOT NULL,
 `col11` smallint(6) NOT NULL,
 PRIMARY KEY (`primaryCol`),
 KEY `col5` (`col5`),
 KEY `col1` (`col1`),
 KEY `col3` (`col3`),
 KEY `col4` (`col4`),
 KEY `col8` (`col8`),
 KEY `col9` (`col9`),
 KEY `CompIndex1` (`col1`,`col8`,`col4`),
 KEY `col2` (`col2`),
 KEY `col10` (`col10`),
 KEY `col11` (`col11`),
 FULLTEXT KEY `col7` (`col7`)
) ENGINE=MyISAM AUTO_INCREMENT=4575350 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

の結果EXPLAIN EXTENDED

id  select_type table   type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  Table1  ref col1,col3,CompIndex1,col2   CompIndex1  5   const   226 100 Using where; Using filesort
4

3 に答える 3

6

(col1、col2、col3)のインデックスをお勧めします。

mysql> CREATE INDEX NewIndex ON Table1 (col1,col2,col3);

mysql> EXPLAIN SELECT *  FROM  `Table1`  WHERE  `col1` =  '145307' 
AND  `col2` =  '0' AND col3 NOT  IN ( 130209, 130839 )  
ORDER BY col4 DESC  LIMIT 0 , 5\G

           id: 1
  select_type: SIMPLE
        table: Table1
         type: ref
possible_keys: col1,col3,CompIndex1,col2,NewIndex
          key: NewIndex
      key_len: 6
          ref: const,const
         rows: 1
        Extra: Using where; Using filesort

col3 の条件は等価比較ではなく、範囲比較であり、インデックスの最後の列である必要があります。

残念ながら、これは、EXPLAIN プランで「ファイルソートを使用する」ことを取り除くことができないことを意味します。一般に、別の列で範囲比較も行っている場合、インデックスを使用して並べ替えを最適化することはできません。

ただし、少なくとも 3 列のインデックスを使用して検索を絞り込むことができるため、ファイルソートはより小さな行セットで作業する必要があり、メモリ内で実行できる可能性があります。

私のプレゼンテーションHow to Design Indexes, Reallyも参照してください。

于 2012-12-12T20:36:49.620 に答える
0

複合インデックスを作成する場合、複合インデックスのメンバーである個々の列にインデックスを作成するのは冗長です。最も頻繁に実行するクエリ、クエリに含まれる各列のカーディナリティ、クエリが返すおおよその行数、テーブル内の合計行数、テーブルが頻繁に更新されるかなどを把握します。インデックスについて覚えておいてください。挿入と更新に対するコスト。

于 2012-12-14T06:17:11.007 に答える
0

現在の最良の答えは、最も恐ろしいものです。EXPLAIN で「ファイルソート」が表示されるたびに、非常に遅くなります。MySQL は一時ファイルを作成する必要があり、ソートにインデックスを使用しないためです!

インデックスは電話帳のようなものです。あなたの場合、正しいインデックスは次のようになります。

(col4、col1、col2、col3、primaryCol)

順番が大事!複合インデックスの左端の部分は、常に順序付けたい列でなければなりません。次に、WHERE 句で使用する他の列を追加します。最後に、MyISAM の場合、主キーも追加する必要があります (InnoDB は自動的に行います)。

また、クエリを変更して、順序付け/フィルタリングと完全な詳細の取得が分離されるようにする必要があります。

SELECT * FROM `Table1` JOIN (
  SELECT primaryKey FROM  `Table1` 
  WHERE  `col1` =  '145307'
  AND  `col2` =  '0'
  AND col3 NOT 
  IN ( 130209, 130839 ) 
  ORDER BY col4 DESC 
  LIMIT 0 , 5
) foo ON Table1.primaryKey=foo.primaryKey

これを EXPLAIN でチェックすると、順序付けとフィルタリングのための適切なインデックスの使用法がわかります。次に、結果の ID がテーブルと再び結合され (別の高速インデックス操作で)、完全な詳細が取得されます。

于 2013-04-09T16:17:58.170 に答える