0

Webサイトでニュースを整理するために使用するMySQLクエリが2つあります。ここに示されているすべてのフィールドは数値(intまたはtinyint)であり、すべてにインデックスが付いています。誰かが私が2つのクエリをスピードアップする複数列のインデックスを構築するのを手伝ってもらえますか?

SELECT MAX(content_time) AS content_time 
  FROM cm_data 
 WHERE content_time < UNIX_TIMESTAMP() 
   AND page = '1' 
   AND (content_type = '1' OR content_type = '5')

SELECT content_id 
  FROM cm_data
 WHERE (content_time < UNIX_TIMESTAMP() 
       OR (hp_time >= UNIX_TIMESTAMP() AND content_time < UNIX_TIMESTAMP()
          )
       )
   AND page = '1' 
   AND (content_type = '1' OR content_type = '5')
 ORDER BY hp_time DESC
     , content_time DESC
 LIMIT 20

そして、これがDBスキーマです。

CREATE TABLE IF NOT EXISTS `cm_data` (
  `content_id` mediumint(8) NOT NULL AUTO_INCREMENT,
  `content_time` int(11) DEFAULT NULL,
  `hp_time` int(11) NOT NULL DEFAULT '0',
  `content_type` tinyint(2) DEFAULT NULL,
  `page` tinyint(2) NOT NULL DEFAULT '1',
  PRIMARY KEY (`content_id`),
  KEY `content_time` (`content_time`),
  KEY `content_type` (`content_type`),
  KEY `page` (`page`),
);
4

1 に答える 1

1

インデックスが常に答えであるとは限りません(特に、多くのINSERTステートメントが予想される場合)。そうは言っても、これらのクエリを最適化するためにできることがいくつかあります。

1)制約が適切に形成されていることを確認します。2番目のクエリでは、基本的にがありますがCase1 OR ( Case2 AND Case1 )、これは単純化してCase1(ブール代数)にすることができます。クエリオプティマイザが確認する前に、これらを可能な限り削減することで、オプティマイザに必要な労力を削減できるだけでなく、解決できないケースをキャッチすることもできます。

2)制約の順序を確認します。クエリオプティマイザが一意でないキーについて特定の順序で制約をチェックすることはドキュメントのどこにも記載されていないため、最適化に関する少しの知識を使用して、クエリを高速化できる可能性があります。一般的に、非整数制約の評価にはコストがかかります(STRINGなど)。あなたの場合、UNIX_TIMESTAMP()はUNSIGNED INTを返しますが、フィールドはINTEGERとして指定されています。これにより、各行のキャスト操作が発生し、コストがかかります。したがって、比較を実行する必要がある回数を減らすことができれば(最初に、より単純な制約を持つ行をフィルターで除外することにより)、実行する必要のある操作が少なくなり、実行時間が短縮されます。

2a)MySQLは関数のインデックスをサポートしていないため、フィールドのデータ型をUNSIGNED INTに変更するか(使用可能な場合は推奨)、フィールドに相当するUNSIGNEDINTを含むトリガーで更新される追加の列を作成できます。 、代わりにインデックスを付けます。後者は理想的ではありませんが、テーブルサイズの増加を犠牲にして、パフォーマンスをいくらか向上させることができます。

于 2012-08-14T19:08:31.233 に答える