2

テーブル:

CREATE TABLE `test` (
  `uid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `rating` smallint(5) unsigned NOT NULL DEFAULT '100',
  PRIMARY KEY (`uid`),
  KEY `rating` (`rating`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

このクエリは十分に速く実行されます (0.015 秒):

SELECT uid FROM test ORDER BY rating DESC LIMIT 0,100

しかし、LIMIT オフセットが大きいと、実行速度が非常に遅くなります (2.215 秒):

SELECT uid FROM test ORDER BY rating DESC LIMIT 10000,100

どうすれば巨大な LIMIT オフセットを取り除くことができますか?!

4

3 に答える 3

6

MySQLではLIMIT 10000, 100、10100レコードをスキャンする必要があります。あなたが窓の中であなたの場所を思い出すことができれば、それはより良いかもしれません:

SELECT uid
FROM test
WHERE rating > :last_rating
ORDER BY rating DESC LIMIT 0,100

この場合、:last_ratingは前のクエリからの最後の評価でした。

于 2012-05-05T06:10:52.730 に答える
1

パフォーマンスを向上させる最も簡単な方法は、主キーで注文することです。

コラムではそれができないので、rating代わりにチートすることができます。

このテーブルを作成します。

CREATE TABLE `test_ranks` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

次に、X時間ごとに実行されるcronスクリプトに次のように記述します(1分、5分...基本的に、更新速度と実行にかかる時間の間の適切な妥協点)。

CREATE TEMPORARY TABLE `_tmp_test_ranks` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `_tmp_test_ranks` (`uid`) VALUES (SELECT `uid` FROM `test` ORDER BY `rating` DESC);

TRUNCATE `test_ranks`;

INSERT INTO `test_ranks` SELECT * from `_tmp_test_ranks`;

DROP TABLE `_tmp_test_ranks`;

これで、実行速度の遅い選択の代わりに、実行速度を上げることができます。

SELECT `uid` FROM `test_ranks` WHERE `id` BETWEEN 10000 AND 10100 ORDER BY `id` ASC
于 2012-05-05T06:11:03.980 に答える