0

元の 3,000 行を複数回複製することによって生成された、約 1 億行のテスト データベース テーブルがあります。このテーブルが、タイムスタンプを持ついくつかのイベントを記述しているとしましょう。現在、クローン作成により、1 日あたり約 1,000 万件のイベントが発生していますが、これは実際のケースとはかけ離れています。そこで、日付列をランダム化し、レコードを数日間分散させたいと思います。これが私が思いついた手順です:

DROP PROCEDURE IF EXISTS `randomizedates`;
DELIMITER //
CREATE PROCEDURE `randomizedates`(IN `daterange` INT)
BEGIN
  DECLARE id INT UNSIGNED;
  DECLARE buf TIMESTAMP;
  DECLARE done INT DEFAULT FALSE;
  DECLARE cur1 CURSOR FOR SELECT event_id FROM events;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  the_loop: LOOP
    FETCH cur1 INTO id;
    IF done THEN
      LEAVE the_loop;
    END IF;
    SET buf = (SELECT NOW() - INTERVAL FLOOR(RAND() * daterange) DAY);
    UPDATE events SET starttime = buf WHERE event_id = id;
  END LOOP the_loop;
  CLOSE cur1;
END //
DELIMITER ;

3k テーブルでは ~6 秒間実行されるため、100m テーブルに適用するには ~50 時間かかります。それをスピードアップする方法はありますか?それとも、私の手順がまったく間違っているのでしょうか?

4

1 に答える 1

1

ただ行う:

set @datarange = 7;
update `events`
set starttime = NOW() - INTERVAL FLOOR(RAND()) * @datarange DAY;

データベースは、手続き型言語 (反復子、for each ループ、配列など) で慣れているように、lopp で単一の行をフェッチして処理するのが得意ではありません。データベースは、本質的に宣言型である SQL の処理に最適であり、最適化されています。言語 - プログラムが実行しなければならないステップを指定するために使用される手続き型言語とは対照的に、取得方法を指定せずに取得したいものを宣言します。

覚えておいてください-行ごと=ゆっくりとゆっくり。

テーブルをシミュレートし、プロシージャを UPDATE と比較する簡単な例を見てください。

drop table `events`;
create table `events` as 
select * from information_schema.tables
where 1=0; 

alter table `events` add column event_id int primary key auto_increment first;

alter table `events` change column create_time starttime timestamp;

insert into `events`
select null, t.*
from information_schema.tables t
cross join (
  select 1 from information_schema.tables
  limit 100
) xx

mysql> select count(*) from `events`;
+----------+
| count(*) |
+----------+
|    17200 |
+----------+

17,000 行のテーブルを作成しました。次に、プロシージャを呼び出します。

mysql> call `randomizedates`(7);
Query OK, 0 rows affected (34.26 sec)

および更新コマンド:

mysql>     set @datarange = 7;
Query OK, 0 rows affected (0.00 sec)

mysql>     update `events`
    ->     set starttime = NOW() - INTERVAL FLOOR(RAND()) * @datarange DAY;
Query OK, 17200 rows affected (0.23 sec)
Rows matched: 17200  Changed: 17200  Warnings: 0

ご覧のとおり - 34 秒 / 0.23 秒 = 14782 % 速い - これは大きな違いです!!!

于 2013-07-31T21:15:19.873 に答える