1

16 000 000の一意の乱数(10桁:範囲1 000 000 000-9 999 999 999)を生成し、それらを空のテーブルに挿入しようとしています(または、空でない場合はこのテーブルを埋めます)。

テーブル:

CREATE TABLE `codes` (
`code_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`code` bigint(20) UNSIGNED NOT NULL,
`is_used` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`code_id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

...そして機能:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `codes`(`minRange` BIGINT UNSIGNED, `maxRange` BIGINT UNSIGNED, `_amount` BIGINT UNSIGNED) RETURNS tinyint(1)
MODIFIES SQL DATA
BEGIN
DECLARE pick BIGINT;


while (SELECT count(*) FROM codes) < _amount do
begin
SET pick = minRange + FLOOR(RAND() * (maxRange - minRange + 1));
INSERT IGNORE INTO codes (code) VALUES (pick);

end;
end while;

RETURN 1;
END$$

DELIMITER ;

-- call: SELECT codes(1000000000,9999999999,16000000);

関数は非常に遅いです:20k行の生成には2.5分かかるので、16M-約33時間...それを最適化する方法はありますか?

4

4 に答える 4

2

あなたが求めているのは撞着語です。16Mの数字が一意である場合、それらはランダムではありません。考えてみてください。真に10桁の乱数には、1/9E9が任意の数である確率があります。しかし、あなたの16M番目の数字は、15,999,999の数字の1つである確率が0であり、残りの数字の1つである確率が1/983,000,001です。常に重複を期待する必要があります。1Bのうち16Mは約1%です。

したがって、私の提案は、(16M +ビット)乱数を生成し、一意の並べ替えを行うことです。16Mに切り捨ててから、ランダムに並べ替えます。これを行うための私のQ&D:

php -r 'for( $i=0;$i<16500000;$i++) echo mt_rand(100000000, 999999999),"\n";'\
  | sort -u | head -16000000 | sort -R > /tmp/loadfile.lst

私の4歳のラップトップで7分強かかりました。最新のクアッドコアデスクトップでは、はるかに高速になります。PHP-CLIを使用したのは、ラップトップにPHP-CLIがあり、mt_randルーチンが優れているためです。これは、3ライナーCプログラムまたは任意の言語として実行できます。Zercmsが言うように、ロードの前にインデックスを無効にし、後で再度有効にする限り、ロードは高速になります。また、列をロードするだけで済みますcode

楽しみ。

于 2012-06-13T18:01:43.233 に答える
1

私が考えることができる最速の方法は、一意の番号を使用してプレーンテキストファイルを生成し、使用することですLOAD DATA INFILE

ALTER TABLEまた、データのロードを開始する前にを使用してキーを無効にし、その後有効にする必要があります

于 2012-06-13T11:45:43.757 に答える
1

挿入された乱数SELECT count(*)ごとにを実行しています。簡単な最適化は、チェックせずに16000000の乱数を詰め込み、実際に挿入された数確認し、最初から追加する残りの数の数で繰り返すことです。

于 2012-06-13T11:49:14.343 に答える
0

おそらく、MySQLではなく、PHPがインストールされている場合は、PHPを介して数値を生成するようにしてください。PHPmt_rand()ははるかに優れたランダム値を生成します。値を配列に入力し、を介して値がすでにそこにあるかどうかを直接確認できますin_array()

また、MySQLは毎回テーブルインデックスを更新する必要があるため、大幅に遅くなります。MySQLで行う必要がある場合は、数値生成時に無効にする必要があります。

于 2012-06-13T11:48:26.050 に答える