3

シナリオの概要:

船にはデータロギングシステムがあり、さまざまなセンサーがリアルタイムデータを読み取り、そのデータを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
4

2 に答える 2

0

解決しました!

setunaに感謝します(コメントを参照)

列cal.dtをNOTNULLに変更し、tmstampをTIMESTAMPまたはDATETIMEとNOTNULLの両方に変更します。〜30,000レコードと適切にインデックス付けされたJOIN条件フィールドを持つJOINは、非常に高速に実行されるはずです。

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
于 2012-08-15T08:36:15.777 に答える
0

cal.dtNOTNULLに変更し、 tmstampTIMESTAMPまたはDATETIMENOTNULLの両方に変更します。〜30,000レコードと適切にインデックス付けされたJOIN条件フィールドを持つJOINは、非常に高速に実行されるはずです。

注: @Knapieはすでにこの回答の結果を示しています。

于 2012-08-15T08:55:24.827 に答える