0

このようなテーブルがあります(説明を簡単にするために多くのフィールドを削除しました)。orderId は、行の重要性を示すために使用される int の非一意の値です (データを返すときにそれによって注文します)。

CREATE TABLE `my_images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orderId` int(11) NOT NULL,
  `slug` varchar(50) NOT NULL,
  `imageFilename` varchar(255) NOT NULL,
  `thumb200` varchar(255) NOT NULL,
  `thumb600` varchar(255) NOT NULL,
  `md5hash` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `orderId` (`orderId`),
  KEY `thumb600` (`thumb600`),
  KEY `slug` (`slug`),
  KEY `multiple_1` (`md5hash`,`orderId`,`thumb200`,`thumb600`),
  KEY `md5hash` (`md5hash`),
  KEY `thumb200` (`thumb200`),
  KEY `thumb200_2` (`thumb200`,`orderId`),
  KEY `orderId_2` (`orderId`,`thumb600`,`thumb200`),
  KEY `thumb600_2` (`thumb600`,`orderId`),
  KEY `thumb600_3` (`thumb600`,`orderId`),
  KEY `orderId_3` (`orderId`,`thumb600`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

はい - orderId をカバーするインデックスがたくさんあります。現在の問題を修正するための試行錯誤と、WHERE ステートメントでこれらのフィールドを使用するための組み合わせです。

とにかく、このコマンドを実行すると:

explain SELECT id FROM my_images
 ORDER BY orderId asc

これを出力します(「インデックスの使用」)

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   index   NULL    orderId 4   NULL    174553  Using index

これは予想通りです - orderId はインデックスです。

しかし、私がこれを行うと:

explain SELECT id,   thumb600, imageFilename,  slug FROM my_images
 ORDER BY orderId asc

これを出力します(filesortを使用):

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   ALL NULL    NULL    NULL    NULL    174553  Using filesort

奇妙なことに、私がこれを行うと

explain SELECT id,  md5hash  FROM my_images
 ORDER BY orderId asc

「インデックスの使用; ファイルソートの使用」と表示されます

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   index   NULL    multiple_1  775 NULL    174553  Using index; Using filesort

私が気づいた理由は、基本的には「select (フィールドの束) orderId limit 4000,3」という遅いクエリを見たからです。常にインデックスを使用するにはどうすればよいですか? 選択したすべてのフィールドを含むインデックスを作成する必要がありますか? もしそうなら、インデックス内のフィールドの順序は重要ですか?

4

2 に答える 2

3

インデックスでカバーされていない列を選択すると、エンジンはそれらの列の値を取得するためにテーブル ルックアップを行う必要があります。

とにかくテーブル全体を選択しているので (WHEREまたはを使用していないLIMIT)、多くのキーシークを行うよりも、テーブルを順番にスキャンしてから並べ替える方が高速です。

また、MySQL遅い行のルックアップを行うことはできません。これは、インデックスを使用している場合でも、オフセットをカウントする前に常にテーブルをルックアップすることを意味します。

テーブル内の非 PK フィールドで並べ替える場合は、次のようにしてInnoDBください。

SELECT  i.*
FROM    (
        SELECT  id
        FROM    my_images
        ORDER BY
                orderId
        LIMIT   4000, 3
        ) q
JOIN    my_images i
ON      i.id = q.id

説明については、私のブログのこの記事を参照してください。

于 2013-04-24T21:23:52.397 に答える