0

プロジェクト テーブルがあり、各プロジェクトには複数のカテゴリが割り当てられています。カテゴリ マッピングはproject_categoryテーブルに格納されます。有効期限が切れていない最近のプロジェクトをすべて一覧表示したいと考えています。これがスキーマ、インデックス、およびクエリです。

スキーマ

Create table projects (
   project_id Bigint UNSIGNED NOT NULL AUTO_INCREMENT,
   project_title Varchar(300) NOT NULL,
   date_added Datetime NOT NULL,
   is_expired Bit(1) NOT NULL DEFAULT false,
Primary Key (project_id)) ENGINE = InnoDB;

Create table project_category (
   project_category_id Int UNSIGNED NOT NULL AUTO_INCREMENT,
   cat_id Int UNSIGNED NOT NULL,
   project_id Bigint UNSIGNED NOT NULL,
Primary Key (project_category_id)) ENGINE = InnoDB;

インデックス

CREATE INDEX project_listing (is_expired, date_added) ON projects;
Create INDEX category_mapping_IDX ON project_category (project_id,cat_id);

クエリ

mysql> EXPLAIN
  SELECT P.project_id
  FROM projects P
  INNER JOIN project_category C USING (project_id)
  WHERE P.is_expired=false
    AND C.cat_id=17
  ORDER BY P.date_added DESC LIMIT 27840,10;
+----+-------------+-------+--------+--------------------------------------------+---------+---------+-------------------------+--------+---------------------------------+
| id | select_type | table | type   | possible_keys                              | key     | key_len | ref                     | rows   | Extra                           |
+----+-------------+-------+--------+--------------------------------------------+---------+---------+-------------------------+--------+---------------------------------+
|  1 | SIMPLE      | C     | ref    | project_id,cat_id,category_mapping_IDX     | cat_id  | 4       | const                   | 185088 | Using temporary; Using filesort |
|  1 | SIMPLE      | P     | eq_ref | PRIMARY,is_expired_INX,project_listing_IDX | PRIMARY | 8       | freelancer.C.project_id |      1 | Using where                     |
+----+-------------+-------+--------+--------------------------------------------+---------+---------+-------------------------+--------+---------------------------------+

MySQL が のインデックスを使用しないproject_category理由と、完全な並べ替えを行う理由を知りたいです。

ファイルの並べ替えを避けるために、次のクエリも試しましたが、どちらも機能していません。

mysql> EXPLAIN
  SELECT P.project_id
  FROM projects P,
  (
    SELECT P.project_id 
    FROM projects P
    INNER JOIN project_category C USING (project_id)
    WHERE C.cat_id=17
  ) F
  WHERE F.project_id=P.project_id
    AND P.is_expired=FALSE
  LIMIT 10;

+----+-------------+------------+--------+--------------------------------------------+---------+---------+-------------------------+--------+-------------+
| id | select_type | table      | type   | possible_keys                              | key     | key_len | ref                     | rows   | Extra       |
+----+-------------+------------+--------+--------------------------------------------+---------+---------+-------------------------+--------+-------------+
|  1 | PRIMARY     | <derived2> | ALL    | NULL                                       | NULL    | NULL    | NULL                    | 110920 |             |
|  1 | PRIMARY     | P          | eq_ref | PRIMARY,is_expired_INX,project_listing_IDX | PRIMARY | 8       | F.project_id            |      1 | Using where |
|  2 | DERIVED     | C          | ref    | project_id,cat_id,category_mapping_IDX     | cat_id  | 4       |                         | 185088 |             |
|  2 | DERIVED     | P          | eq_ref | PRIMARY                                    | PRIMARY | 8       | freelancer.C.project_id |      1 | Using index |
+----+-------------+------------+--------+--------------------------------------------+---------+---------+-------------------------+--------+-------------+
4

1 に答える 1

0

あなたの問題はここにあります:

Create INDEX category_mapping_IDX ON project_category (project_id,cat_id);

cat_id はインデックスの最初の部分ではないため、単一の cat_id をサブ選択しようとしている場合、このインデックスは役に立ちません。インデックスを連結された文字列と考えると、使用できない理由がわかります。順番を入れ替えます:

Create INDEX category_mapping_IDX ON project_category (cat_id, project_id);
于 2012-12-15T21:32:23.250 に答える