2

インデックス (または実際にはクエリ自体) を使用して MySQL クエリを最適化するための助けがあれば幸いです。

テーブル構造:

CREATE TABLE IF NOT EXISTS `match_current` (
  `partnership_id` int(11) NOT NULL AUTO_INCREMENT,
  `runs` int(5) NOT NULL DEFAULT '0',
  `balls` int(5) NOT NULL DEFAULT '0',
  `user1_id` bigint(11) NOT NULL,
  `user1_firstname` char(20) NOT NULL,
  `user1_lastname` char(20) NOT NULL,
  `user1_runs` int(5) NOT NULL DEFAULT '0',
  `user1_balls` int(5) NOT NULL DEFAULT '0',
  `user1_strike` tinyint(1) NOT NULL DEFAULT '1',
  `user1_out` tinyint(1) NOT NULL DEFAULT '0',
  `user1_retired` tinyint(1) NOT NULL DEFAULT '0',
  `user2_id` bigint(11) NOT NULL,
  `user2_firstname` char(20) NOT NULL,
  `user2_lastname` char(20) NOT NULL,
  `user2_runs` int(5) NOT NULL DEFAULT '0',
  `user2_balls` int(5) NOT NULL DEFAULT '0',
  `user2_strike` tinyint(1) NOT NULL DEFAULT '0',
  `user2_out` tinyint(1) NOT NULL DEFAULT '0',
  `user2_retired` tinyint(1) NOT NULL DEFAULT '0',
  `last_over` char(15) NOT NULL,
  `ball_by_ball` varchar(1000) NOT NULL,
  `facebook` tinyint(1) NOT NULL DEFAULT '0',
  `friends` tinyint(1) NOT NULL DEFAULT '0',
  `nudge` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `started` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `status` tinyint(1) NOT NULL DEFAULT '1',
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`partnership_id`),
  UNIQUE KEY `user1_id_2` (`user1_id`,`user2_id`,`facebook`),
  KEY `user2_id` (`user2_id`),
  KEY `user1_id` (`user1_id`),
  KEY `facebook` (`facebook`),
  KEY `status` (`status`),
  KEY `friends` (`friends`),
  KEY `timestamp` (`timestamp`),
  KEY `user1_id_3` (`user1_id`,`user1_strike`),
  KEY `user2_id_2` (`user2_id`,`user2_strike`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=36139 ;

サンプルクエリ:

SELECT * 
FROM match
WHERE status = 1 
AND (
  (user1_id=1234 AND user1_strike=1) OR 
  (user2_id=4321 AND user2_strike=1)
) 
ORDER BY timestamp ASC

クエリは明らかに機能しており、それほど悪くはありませんでしたが、最近トラフィックが大幅に増加し、苦労し始めていることがわかります。

乾杯!

4

2 に答える 2

2

クエリを最適化する際に留意すべきことの 1 つは、MySQL がクエリを実行するときに1 つのインデックスのみを選択することです。考えられるフィールドの組み合わせをやみくもにインデックス付けしても、あまり役に立たず、実際には挿入が遅くなります。

user1これは、2 人のプレーヤーがチームを形成している典型的なテーブルのように見えます。これは、クエリ対象のユーザーが参加するかどうか、またはuser2両方を検索するかわからないためです。これにより、すべてのキーが拒否され、結果としてテーブル スキャンが実行される可能性があります。

(user_id, partnership_id)私のアドバイスは、テーブルをわずかに非正規化し、複数の主キーと組み合わせて保存する別のテーブルを作成することです。各レコードpartnershipsは、このテーブルの 2 つのレコードです。これにより が不要にORなり、単純な を使用JOINしてより大きなテーブルから必要な情報を取得できます。

これらの問題を調査するためEXPLAIN <query>に、MySQL がどのようにクエリを「攻撃」するかを確認できます。

于 2012-12-20T10:51:37.177 に答える
0

本当に全部必要ですか?

SELECT *

WHERE 句のインデックスを作成する

INDEX(user1_id, user1_strike, user2_id, user2_strike)

timestemp を含めて、インデックスで順序を ASC に設定することもできます。

これらに加えて、データベースのテーブルに追加のインデックス作成と再設計が必要になる場合があります。また、SQL サーバーの設定を確認することも検討してください (InnoDB テーブルを使用し、サーバーの正しいキャッシュ/メモリ制限を設定します)。

于 2012-12-20T10:37:08.620 に答える