0

読み取りを高速化するために MySQL テーブルを最適化しようとしています。読み取りと書き込みの比率は約 100:1 であるため、複数のインデックスを使用して書き込みのパフォーマンスを犠牲にする傾向があります。

私のテーブルに関連するフィールドは次のとおりで、約 200000 レコードが含まれています

CREATE TABLE `publications` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  -- omitted fields
  `publicaton_date` date NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '0',
  `position` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  -- these are just attempts, they are not production index
  KEY `publication_date` (`publication_date`),
  KEY `publication_date_2` (`publication_date`,`position`,`active`)
) ENGINE=MyISAM;`enter code here`

このテーブルのデータにアクセスするために Ruby on Rails を使用しているので、このテーブルのデフォルトのスコープを定義しました。

default_scope where(:active => true).order('publication_date DESC, position ASC')

つまり、デフォルトでは、このテーブル内のすべてのクエリは、次の SQL フラグメントで自動的に完了されるため、ほとんどすべてのクエリがこれらの条件を満たしていると想定できます。

WHERE `publications`.`active` = 1 ORDER BY publication_date DESC, position

したがって、私は主にこの種のクエリの最適化に加えて、WHERE 条件で publication_date を使用したクエリに関心があります。

次のインデックスをさまざまな組み合わせで試しました(同時に複数でも)

`publication_date`
`publication_date`,`position`
`publication_date`,`position`,`active`

ただし、これはまだインデックスを適切に使用しておらず、ファイルソートを使用しているため、単純なクエリです

SELECT  `publications`.* FROM `publications`  
WHERE `publications`.`active` = 1 
AND (id NOT IN (35217,35216,35215,35218)) 
ORDER BY publication_date DESC, position
LIMIT 8 OFFSET 0
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: publications
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 34903
        Extra: Using where; Using filesort
1 row in set (0.00 sec)

私の問題に関するいくつかの考慮事項:

  • MySQL のドキュメントによると、ORDER BY 句で ASC と DESC を混在させると、順序付けに複合インデックスを使用できません。
  • activeはブール値フラグなので、スタンドアロン インデックスに配置しても意味がありません (可能な値は 2 つだけです) が、常に WHERE 句で使用されるため、Extra での where の使用を避けるために、インデックスのどこかに表示する必要があります。
  • position可能な値がほとんどない整数であり、常にスコープで使用されるpublication_dateため、スタンドアロンのインデックスに含めるのは無意味だと思います
  • 多くのクエリpublication_dateで where 部分が使用されるため、たとえ冗長で複合インデックスの最初の列であっても、スタンドアロン インデックスにも含めると便利です。
4

1 に答える 1