8

穴のない自動インクリメントされた主キーに基づいて、テーブルからランダムな行を選択しようとしています。

テーブルスキーマ:

CREATE TABLE IF NOT EXISTS `testTable` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `data` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;

INSERT INTO `testTable` (`id`, `data`) VALUES
(1, 'hello'),
(2, 'world'),
(3, 'new'),
(4, 'data'),
(5, 'more and more'),
(6, 'data '),
(7, 'more rows here'),
(8, 'most rows here'),
(9, 'testing'),
(10,'last');

クエリ:

1 /explain select * from testTable where id = ceil(Rand()*10) limit 1 ;

http://sqlfiddle.com/#!2/6e2b1/1

結果 :

| ID | SELECT_TYPE |     TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |       EXTRA |
--------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | testTable |  ALL |        (null) | (null) |  (null) | (null) |   10 | Using where |

2/explain select * from testTable where id = 7 limit 1 ;

http://sqlfiddle.com/#!2/6e2b1/2

結果:

| ID | SELECT_TYPE |     TABLE |  TYPE | POSSIBLE_KEYS |     KEY | KEY_LEN |   REF | ROWS | EXTRA |
---------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | testTable | const |       PRIMARY | PRIMARY |       4 | const |    1 |       |

query#1がインデックスを使用しないのはなぜですか。ceil(rand()*10)理想的には、主キーと比較できる定数に評価する必要がありますか?オプティマイザはそのように機能するべきではありませんか?または、ここで明らかな何かが欠けていますか?

4

2 に答える 2

6

キーはそのクエリで使用できません。これRAND()は、行ごとに呼び出され、毎回異なる値を返すためです。

代わりに次のコードを試すことができます。

SET @rand_value := CEIL(RAND()*10);
EXPLAIN SELECT * FROM testTable WHERE id = @rand_value;

最初にランダムな値を計算して変数に割り当て、次にそれをクエリで使用します。
真空計で指摘されているように、これLIMIT 1は役に立ちません。条件が主キーに適用されるため、クエリが複数の行を返すことはありません。

このクエリでは、出力は次のようになります。

| ID | SELECT_TYPE |     TABLE |  TYPE | POSSIBLE_KEYS |     KEY | KEY_LEN |   REF | ROWS | EXTRA |
---------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | testTable | const |       PRIMARY | PRIMARY |       4 | const |    1 |       |
于 2012-09-11T07:49:41.700 に答える
3

MySQLのドキュメントRAND()から:

RAND()句内は、が実行さWHEREれるたびに再評価されます。WHERE

したがって、主キーを定数と比較するのではなく、毎回(この場合は行ごとに)変化する値です。クエリでを削除するLIMIT 1と、一致するさまざまなPKを含む行がさらに表示されます。これは、「毎回再評価される」動作を示しています。

編集:最初に乱数を生成し、次に一致するPKを持つ行を取得する方法としてJocelynの例を参照してくださいidLIMIT 1必須ではありませんが、ところで)。同様にNajzeroのコメントで述べられています。

于 2012-09-11T08:01:21.610 に答える