シナリオの概要:
船にはデータロギングシステムがあり、さまざまなセンサーがリアルタイムデータを読み取り、そのデータをMySQLデータベースに保存しています。
各センサーにはテーブルがあり、瞬時のセンサー値にタイムスタンプが付けられ、データベースに保存されます。
現在の要件は、すべてのセンサーのデータを、2つの日時値の間で1分あたりに平均化された値を持つ単一のテーブルにマージすることです。
これが私がこれまでにしたことです:
1.カレンダテーブルを作成するためのストアドプロシージャを作成しました。 カレンダプロシージャは、指定された2つの日時値の間に日時スタンプを含むテーブルを作成します。クルーズレポートの場合、カレンダーテーブルで作業しているのは次のようになります。
cal
-------------------+
dt
-------------------+
2012-07-09 00:00:00
2012-07-09 00:01:00
2012-07-09 00:02:00
... etc
2012-07-29 23:57:00
2012-07-29 23:58:00
2012-07-29 23:59:00
合計30241レコード、0.016秒でフェッチされるため、問題はありません。
2.分ごとに平均化されたセンサー値の一時テーブルを作成しました。
平均化されたセンサーテーブルの例:
tbl_gyro_hdt_1min_ave
-------------------+------------------
tmstamp | average_heading
-------------------+------------------
2012-07-09 00:00:00, 135.633333333333
2012-07-09 00:01:00, 135.633333333333
2012-07-09 00:02:00, 136.1
2012-07-09 00:03:00, 135.433333333333
etc...
29546 records fetched in 0.047 secs
および別のセンサーテーブル:
tbl_par_sensor_1min_ave
-------------------+------------------
tmstamp | average_par
-------------------+------------------
2012-07-09 00:00:00, 16.269949
2012-07-09 00:01:00, 16.270832
2012-07-09 00:02:00, 16.2637752
2012-07-09 00:03:00, 16.2678025
2012-07-09 00:04:00, 16.269324
2012-07-09 00:05:00, 16.2721382
etc...
29543 records fetched in 0.047 secs
3.ここで、一時テーブルをカレンダーテーブルに結合すると、ホイールが外れます。
単一のテーブルをカレンダーテーブルに結合するには、次のようにします。
SELECT cal.dt, tbl_gyro_hdt_1min_ave.average_heading
FROM cal
LEFT JOIN tbl_gyro_hdt_1min_ave
ON cal.dt = tbl_gyro_hdt_1min_ave.tmstamp
上記のクエリについて説明します。
+----+---------------+-----------------------+--------+---------------+-------+---------+------+-------+-------------+
| Id | Select_Type | Table | Type | Possible_Keys | Key | Key_Len | Ref | Rows | Extra |
+----+---------------+-----------------------+--------+---------------+-------+---------+------+-------+-------------+
| 1 | SIMPLE | cal | index | NULL | dt | 9 | NULL | 30243 | Using index |
| 1 | SIMPLE | tbl_gyro_hdt_1min_ave | ALL | date_index | NULL | NULL | NULL | 29546 | |
+----+---------------+-----------------------+--------+---------------+-------+---------+------+-------+-------------+
非常に小さなデータセットの場合、これは正常に機能しますが、上記の例では、ハングします。すべてのテーブルにインデックスを追加しようとしましたが、同じ結果になりました。
編集> 完全なデータセットに対してこれを一晩実行させます。
結果:
30243レコードを取得しました。
持続時間:23.697秒、3000.352秒でフェッチ
次のステップは、次のようにカレンダーテーブルに対して3つ以上のテーブルを結合することです。
SELECT cal.dt, tbl_par_sensor_1min_ave.average_par, tbl_gyro_hdt_1min_ave.average_heading
FROM tbl_par_sensor_1min_ave
LEFT JOIN cal
ON cal.dt = tbl_par_sensor_1min_ave.tmstamp
LEFT JOIN tbl_gyro_hdt_1min_ave
ON cal.dt = tbl_gyro_hdt_1min_ave.tmstamp
当然のことながら、これもハングします。
任意のポインタをいただければ幸いです。
以下のコメントで要求されているように、テーブルスキーマは次のとおりです。
show columns from cal;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| dt | datetime | YES | MUL | NULL | |
+-------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)
show columns from tbl_gyro_hdt_1min_ave;
+-----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| tmstamp | varchar(24) | YES | MUL | NULL | |
| average_heading | double | YES | | NULL | |
+-----------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
show columns from tbl_par_sensor_1min_ave;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| tmstamp | varchar(24) | YES | MUL | NULL | |
| average_par | double | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
解決済み:
setunaの変更を実装した後:
シングルアウタージョイン:
SELECT cal.dt, tbl_gyro_hdt_1min_ave.average_heading
FROM cal
LEFT JOIN tbl_gyro_hdt_1min_ave
ON cal.dt = tbl_gyro_hdt_1min_ave.tmstamp
Fetched 30243 records
Duration: 0.015 sec
Fetched in: 0.172 sec
ダブルアウタージョイン:
SELECT cal.dt, tbl_gyro_hdt_1min_ave.average_heading, tbl_par_sensor_1min_ave.average_par
FROM cal
LEFT JOIN tbl_gyro_hdt_1min_ave
ON cal.dt = tbl_gyro_hdt_1min_ave.tmstamp
LEFT JOIN tbl_par_sensor_1min_ave
ON cal.dt = tbl_par_sensor_1min_ave.tmstamp
Fetched 29543 records
Duration: 0.000s
Fetched in: 0.281 sec