0

数百万行のテーブルがあり、特定の ID の最後の行を取得する必要があります

たとえば、device_id = 123 を持つ最後の行 AND device_id = 1234 を持つ最後の行

テーブルが非常に大きく、順序付けに時間がかかるため、テーブルを順序付けせずに最後の 200 を選択し、それらの 200 を順序付けして必要な行をフェッチすることは可能ですか?

どうすればいいですか?

よろしくお願いします。

アップデート

私のPostgreSQLバージョンは9.2.1です

サンプルデータ:

time                      device_id         data       data ....
"2013-03-23 03:58:00-04" | "001EC60018E36" | 66819.59 | 4.203
"2013-03-23 03:59:00-04" | "001EC60018E37" | 64277.22 | 4.234
"2013-03-23 03:59:00-04" | "001EC60018E23" | 46841.75 | 2.141
"2013-03-23 04:00:00-04" | "001EC60018E21" | 69697.38 | 4.906
"2013-03-23 04:00:00-04" | "001EC600192524"| 69452.69 | 2.844
"2013-03-23 04:01:00-04" | "001EC60018E21" | 69697.47 | 5.156
....

このデータの SQLFiddle を参照してください

したがって、device_id = 001EC60018E21 の場合、その device_id を持つ最新の行が必要になります。その device_id を持つ最後の行が必要な行であることは被付与者ですが、テーブルの最後の行である場合とそうでない場合があります。

4

2 に答える 2

2

device_id個人的には、上と降順の複合インデックスを作成しますtime

CREATE INDEX table1_deviceid_time ON table1("device_id","time" DESC);

次に、サブクエリを使用しtimeてそれぞれの最高値を見つけdevice_id、サブクエリの結果をメイン テーブルと結合しdevice_idtime関連するデータを見つけます。たとえば、次のようになります。

SELECT t1."device_id", t1."time", t1."data", t1."data1"
FROM Table1 t1
INNER JOIN (
  SELECT t1b."device_id", max(t1b."time") FROM Table1 t1b GROUP BY t1b."device_id"
) last_ids("device_id","time") 
ON (t1."device_id" = last_ids."device_id" 
    AND t1."time" = last_ids."time");

この SQLFiddleを参照してください。

各デバイス ID の最高のタイムスタンプのトリガーベースの具体化されたビューを維持すると役立つ場合があります。ただし、接続が更新ロックを求めて競合するために、ほとんどの接続が特定のデバイス ID のデータを挿入できる場合、これにより同時実行の問題が発生します。また、upsert を実行しなければならないので、新しいデバイス ID がいつ表示されるかわからない場合も面倒です。これは非常に非効率的で扱いにくいものです。さらに、サマリー テーブルによって作成される追加の書き込み負荷と自動バキューム作業は、それだけの価値がない場合があります。より高価なクエリの価格を支払う方が良いかもしれません。

ところで、time組み込みのデータ型名であるため、列のひどい名前です。可能であれば、より適切なものを使用してください。

于 2013-04-05T02:03:06.963 に答える
1

各 device_id の「最後の」行を取得する一般的な方法は次のようになります。

select *
from Table1 
inner join (select device_id, max(time) max_time
            from Table1
            group by device_id) T2
   on Table1.device_id = T2.device_id
  and Table1.time = T2.max_time;

ORDER BY を使用せずに「最後の」200 個の device_id 番号を取得することは実際には実用的ではありませんが、そもそもなぜそれを行う必要があるのか​​ は明確ではありません。200 が任意の数値である場合は、代わりに任意の時間に基づくテーブルのサブセットを使用することで、パフォーマンスを向上させることができます。

select *
from Table1 
inner join (select device_id, max(time) max_time
            from Table1
            where time > '2013-03-23 12:03'
            group by device_id) T2
on Table1.device_id = T2.device_id
and Table1.time = T2.max_time;
于 2013-04-05T02:03:24.713 に答える