2

ここで見つけたのと同じ問題があります

MySQL-構造は同じでデータが異なる複数のテーブルからデータを選択します

構造は同じでデータが異なる多くのMySQLテーブルからデータを選択する必要があります(table_0、table_1、table_2などをtable_5に分割して、数百万のデータレコードを配布します)。

各デバイスのデータレコードを生成するハードウェアは、タイムスタンプフィールドに従ってテーブルからテーブルに移動します。これは一意ではありません。たとえば、table_0の50レコードのタイムスタンプは同じである可能性があります。データがtable_5の最後に到達すると、table_0に戻り、そこでデータの上書きを開始します。時間範囲内で各デバイスのデータを取得する必要があります。

各テーブルのデータ列(table_0、table_1 ...からtable_5まで):
timestamp, robotGroupID, robotID, sensor1, sensor2, sensor3, ... (many of them)

ただし、テーブルは巨大であり、UNION ALL(DISTINCTよりも高速に読み取ります)は、6はもちろん、2つのテーブルでも、実行に永遠にかかります。たとえば、以下の2つのテーブルについて説明します。

PHPでのMySQLステートメント:(センサー1、センサー2、センサー3のみを示しています)
(SELECT sensor1, sensor2, sensor3 FROM table_0 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)
UNION ALL
(SELECT sensor1, sensor2, sensor3 FROM table_1 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)

注意:テーブル名を除いて、まったく同じクエリです。時間範囲内のロボットのセンサーデータは、一度に1つ、1つ、または複数のテーブルにまたがることがあります。

各時間範囲内のロボットからのレポート数を事前に知ることができないため、LIMITを使用できません。会社のデータベースへの読み取り専用アクセスしか持っていないMERGESTORAGEENGINEcosを使用できません。

クエリを実行する前に、各テーブルでcount(robotID)などを使用して確認することを考えていますが、このcosの使い方がわかりません。私はかなりの初心者です。

図よりも列が多いので、6つのテーブルともっと多くの列でこれをより速く動作させるにはどうすればよいと思いますか?前もって感謝します!

4

3 に答える 3

1

RobotIDフィールドとTimestampフィールドにインデックスが付けられていますか?

少なくとも(RobotId、timestamp)のマルチフィールドインデックスを追加します。

テーブルへの読み取り専用アクセス権があるとのことですが、このインデックスの追加をリクエストできますか?投稿された元のクエリと更新されたクエリの両方に役立つと確信しています。

于 2010-09-03T14:14:17.860 に答える
0

私はまだ初心者のPHP/MySQLコーダーであることを告白しなければなりませんが、多くのアイデアがあります。だから私のコードはおそらく「汚い」です。

だから私は前進するためにこのように問題を解決しましたが、より良い解決策を歓迎します。奇妙な構文については、このプロジェクトでさまざまなRBDMSタイプを使用しているため、PHPPDOに基づいて構築されたデータベースクラスを使用しています。

$ myQuery_start変数には、他の列の名前とセンサー1〜3を追加しました。次に、 各テーブルのクエリにUNIONALLを追加する必要があるかどうかを確認します。次のテーブルに添付するデータレコードがない場合は、UNIONALLを使用する必要はありません。 次に、テーブルクエリを作成し、組み合わせて完全なクエリを作成します 。次に連結 します。 最後に$ myQueryを実行して、必要に応じてすべてのデータを生成します。
$myQuery_start = "(SELECT sensor1, sensor2, sensor3 FROM ";
$myQueryCount_start = "(SELECT COUNT(*) FROM ";
$myQuery_stop = " WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop.")";

$count_0 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_0".$myQuery_stop)->fetchColumn();
$count_1 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_1".$myQuery_stop)->fetchColumn();
$count_2 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_2".$myQuery_stop)->fetchColumn();
$count_3 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_3".$myQuery_stop)->fetchColumn();
$count_4 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_4".$myQuery_stop)->fetchColumn();
$count_5 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_5".$myQuery_stop)->fetchColumn();


$union_0 = (($count_1 + $count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_1 = (($count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_2 = (($count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_3 = (($count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_4 = (($count_5) > 0)?" UNION ALL ":"";



$query_0 = ($count_0 > 0)?$myQuery_start."ip_minute_stats_0".$myQuery_stop.$union_0:"";
$query_1 = ($count_1 > 0)?$myQuery_start."ip_minute_stats_1".$myQuery_stop.$union_1:"";
$query_2 = ($count_2 > 0)?$myQuery_start."ip_minute_stats_2".$myQuery_stop.$union_2:"";
$query_3 = ($count_3 > 0)?$myQuery_start."ip_minute_stats_3".$myQuery_stop.$union_3:"";
$query_4 = ($count_4 > 0)?$myQuery_start."ip_minute_stats_4".$myQuery_stop.$union_4:"";
$query_5 = ($count_5 > 0)?$myQuery_start."ip_minute_stats_5".$myQuery_stop:"";


$myQuery = $query_0.$query_1.$query_2.$query_3.$query_4.$query_5;

少なくとも、これは以前のUNION ALLの使用方法の約8倍高速なので、これは有効だと思います。提案されたさらなる最適化はありますか?

于 2010-09-03T13:37:21.743 に答える
0

データベース構造を変更できるように説得できれば、MySQLパーティショニングを使用してデータベースのレイアウトを大幅に最適化できます。「範囲パーティショニング」を調査し、MySQLにデータを非表示のサブテーブルに自動的にソートしてSELECT結果をより迅速に処理するように指示するパーティショニングルールを設定することをお勧めします。複数のテーブルも必要ありません。

http://dev.mysql.com/doc/refman/5.1/en/partitioning-overview.htmlを参照してください

于 2012-08-15T23:03:08.297 に答える