1

実行速度が非常に遅いクエリがあります。

実行には約7秒かかります。

ただし、クエリから「およびタイムスタンプ> 20130201」を削除すると、実行にかかる時間は400ミリ秒未満になります。

おそらくタイムスタンプフィールドはインデックスに登録されていないと思いましたが、インデックスに登録されているので、このような日付をクエリに追加すると遅くなるのはなぜでしょうか。

可能であれば、クエリのその部分を削除したくないのですが、そこにあると、なぜそれほど遅くなるのかわかりません。

クエリ:

select p1_score,p2_score,p3_score,p4_score from game where  (p1_user_id='$uid' or p2_user_id='$uid' or p3_user_id='$uid' or p4_user_id='$uid') and turn=0 and timestamp > 20130201

説明:

1   SIMPLE  game    range   p1_user_id,p2_user_id,p3_user_id,p4_user_id,turn,timestamp  timestamp   4   NULL    51486   Using where

SQLの作成:

CREATE TABLE `game` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `p1_user_id` varchar(100) NOT NULL DEFAULT '',
  `p2_user_id` varchar(100) NOT NULL DEFAULT '',
  `p3_user_id` varchar(100) NOT NULL DEFAULT '',
  `p4_user_id` varchar(100) NOT NULL DEFAULT '',
  `player_one_name` varchar(100) DEFAULT NULL,
  `player_two_name` varchar(100) DEFAULT NULL,
  `player_three_name` varchar(100) DEFAULT NULL,
  `player_four_name` varchar(100) DEFAULT NULL,
  `player_one_email` varchar(100) DEFAULT NULL,
  `player_two_email` varchar(100) DEFAULT NULL,
  `player_three_email` varchar(100) DEFAULT NULL,
  `player_four_email` varchar(100) DEFAULT NULL,
  `p1_score` bigint(10) DEFAULT '0',
  `p2_score` bigint(10) DEFAULT '0',
  `p3_score` bigint(10) DEFAULT '0',
  `p4_score` bigint(10) DEFAULT '0',
  `game_name` varchar(255) DEFAULT NULL,
  `players` smallint(1) DEFAULT NULL,
  `turn` varchar(10) DEFAULT NULL,
  `turn_num` smallint(10) DEFAULT '0',
  `layout` longtext,
  `verify` varchar(40) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `message` longtext,
  `tourn` smallint(5) NOT NULL DEFAULT '0',
  `round` smallint(4) NOT NULL DEFAULT '0',
  `tourn_id` varchar(20) NOT NULL DEFAULT '',
  `move_history` longtext NOT NULL,
  `next_turn` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `tourn` (`tourn`),
  KEY `by_player_one_email` (`player_one_email`(10)),
  KEY `by_player_two_email` (`player_two_email`(10)),
  KEY `by_player_three_email` (`player_three_email`(10)),
  KEY `by_player_four_email` (`player_four_email`(10)),
  KEY `p1_user_id` (`p1_user_id`),
  KEY `p2_user_id` (`p2_user_id`),
  KEY `p3_user_id` (`p3_user_id`),
  KEY `p4_user_id` (`p4_user_id`),
  KEY `turn` (`turn`),
  KEY `verify` (`verify`),
  KEY `next_turn` (`next_turn`),
  KEY `timestamp` (`timestamp`),
  KEY `round` (`round`),

) ENGINE=MyISAM DEFAULT CHARSET=latin1;
4

1 に答える 1

1

タイムスタンプ条件のないクエリが高速で実行される場合、それをサブクエリとして持つことは、理論的には同じように高速に実行されるはずです。パフォーマンスの違いがクエリオプティマイザのバグによって引き起こされていると仮定すると、これは同等のパフォーマンスを持つはずです。

SELECT * FROM (query without timestamp condition) t WHERE timestamp > 20130201

もちろんこれは単なる憶測です。テーブル、クエリ、およびクエリの説明プランを知らなければ、質問に明確な答えを出すことは不可能です。

更新:テーブルの説明と説明プランができたので、クエリが列で定義されたインデックスを使用していることがわかりtimestampます。クエリは51,000を超える行を検査することになるため、このインデックスはこのクエリには適していません。インデックスヒントを使用すると、MySQLに別のインデックスの方が適している可能性があることを伝えることができます。

たとえば、これはユーザーIDのインデックスを使用する必要があります。これは、次の制限なしでクエリのように実行する必要がありますtimestamp

SELECT ... from game USE INDEX (p1_user_id,p2_user_id,p3_user_id,p4_user_id)
WHERE ...

または、MySQLにのインデックスを無視するように依頼することもできますtimestamp。そのため、他の、できればより適切なインデックスを使用する必要があります。

SELECT ... from game IGNORE INDEX (timestamp) WHERE ...

クエリは、複数列のインデックスを作成することでおそらくメリットがあります。

于 2013-03-24T16:32:54.617 に答える