如何优化VIEW或SELECT?

时间:2017-11-26 20:32:13

标签: postgresql optimization postgresql-performance

我创建了名为 HistoriaTras 的视图,这意味着路线历史。

CREATE VIEW historiatras AS
SELECT
DataRozpoczeciaTrasy.deviceid AS deviceid,
DataZakonczeniaTrasy.ts - DataRozpoczeciaTrasy.ts AS RoznicaCzasu,
DataRozpoczeciaTrasy.ts AS RozpoczecieTrasy, DataZakonczeniaTrasy.ts AS ZakonczenieTrasy
FROM DEVICE_DATA DataRozpoczeciaTrasy
JOIN DEVICE_DATA DataZakonczeniaTrasy ON DataRozpoczeciaTrasy.deviceid = DataZakonczeniaTrasy.deviceid AND mod(DataZakonczeniaTrasy.inputs,2)=0 AND DataZakonczeniaTrasy.eventid = 11 AND DataZakonczeniaTrasy.ts > DataRozpoczeciaTrasy.ts
WHERE mod(DataRozpoczeciaTrasy.inputs,2)=1
AND DataRozpoczeciaTrasy.eventid = 11

ts =时间戳
DataRozpoczeciaTrasy =开始路线的日期
DataZakonczeniaTrasy =停止路线的日期
RoznicaCzasu = DataRozpoczeciaTrasy之间的时间 - DataZakonczeniaTrasy

如果我在下面做SELECT,一切都很好,但是花了太多时间~27秒 - 并且它不包含所有路线(因为我从一天中选择并选择一个设备 - 85758):

SELECT * FROM HistoriaTras Trasy
WHERE RoznicaCzasu = (SELECT MIN(Trasy1.RoznicaCzasu) 
                      FROM HistoriaTras Trasy1
                      WHERE Trasy.RozpoczecieTrasy = Trasy1.RozpoczecieTrasy) 
   AND deviceid = 85758 
   AND RozpoczecieTrasy > '2017-11-05 00:00:00' 
   AND RozpoczecieTrasy < '2017-11-06 00:00:00'

如果我删除:

AND deviceid = 85758 AND RozpoczecieTrasy > '2017-11-05 00:00:00' AND RozpoczecieTrasy < '2017-11-06 00:00:00'

这需要太多时间。我没有测试它,但需要很长时间。

我在device_data表中有大约100 k行。 朋友们,请写信给我如何优化此选择或查看?我正在使用PostgreSQL 10。

我粘贴解释SELECT的分析因为不允许分析VIEW:

Nested Loop  (cost=0.00..21281.66 rows=1 width=40) (actual time=3973.445..982716.756 rows=380 loops=1)
  Join Filter: ((datazakonczeniatrasy.ts > datarozpoczeciatrasy.ts) AND (datarozpoczeciatrasy.deviceid = datazakonczeniatrasy.deviceid) AND ((datazakonczeniatrasy.ts - datarozpoczeciatrasy.ts) = (SubPlan 1)))
  Rows Removed by Join Filter: 142880
  ->  Seq Scan on device_data datarozpoczeciatrasy  (cost=0.00..5259.22 rows=1 width=16) (actual time=0.046..17.667 rows=380 loops=1)
        Filter: ((eventid = '11'::numeric) AND (mod(inputs, '2'::numeric) = '1'::numeric))
        Rows Removed by Filter: 97518
  ->  Seq Scan on device_data datazakonczeniatrasy  (cost=0.00..5259.22 rows=1 width=16) (actual time=0.011..17.850 rows=377 loops=380)
        Filter: ((eventid = '11'::numeric) AND (mod(inputs, '2'::numeric) = '0'::numeric))
        Rows Removed by Filter: 97521
  SubPlan 1
    ->  Aggregate  (cost=10763.19..10763.20 rows=1 width=16) (actual time=34.834..34.834 rows=1 loops=28011)
          ->  Nested Loop  (cost=0.00..10763.19 rows=1 width=16) (actual time=9.246..34.805 rows=112 loops=28011)
                Join Filter: ((datazakonczeniatrasy_1.ts > datarozpoczeciatrasy_1.ts) AND (datarozpoczeciatrasy_1.deviceid = datazakonczeniatrasy_1.deviceid))
                Rows Removed by Join Filter: 270
                ->  Seq Scan on device_data datarozpoczeciatrasy_1  (cost=0.00..5503.96 rows=1 width=16) (actual time=5.930..17.172 rows=1 loops=28011)
                      Filter: ((eventid = '11'::numeric) AND (datarozpoczeciatrasy.ts = ts) AND (mod(inputs, '2'::numeric) = '1'::numeric))
                      Rows Removed by Filter: 97897
                ->  Seq Scan on device_data datazakonczeniatrasy_1  (cost=0.00..5259.22 rows=1 width=16) (actual time=0.012..17.327 rows=377 loops=28407)
                      Filter: ((eventid = '11'::numeric) AND (mod(inputs, '2'::numeric) = '0'::numeric))
                      Rows Removed by Filter: 97521
Planning time: 0.699 ms
Execution time: 982717.118 ms

我的表:

CREATE TABLE "public"."device_data" ( 
 "deviceid" Bigint REFERENCES cars (deviceid),
 "ts" Timestamp Without Time Zone,
 "longitude" Double Precision,
 "lattitude" Double Precision,
 "speedgps" Numeric( 5, 0 ),
 "heading" Numeric( 5, 0 ),
 "altitude" Numeric( 5, 0 ),
 "satelite" Numeric( 3, 0 ),
 "eventid" Numeric( 3, 0 ),
 "mileagegps" Numeric( 20, 0 ),
 "inputs" Numeric( 5, 0 ),
 "voltageanalog1" Numeric( 4, 2 ),
 "voltageanalog2" Numeric( 4, 2 ),
 "voltageanalog3" Numeric( 4, 2 ),
 "voltageanalog4" Numeric( 4, 2 ),
 "voltageanalog5" Numeric( 4, 2 ),
 "outputs" Numeric( 3, 0 ),
 "totaldistance" Numeric( 20, 0 ),
 "totalfuel" Numeric( 20, 0 ),
 "vehiclespeed" Numeric( 5, 0 ),
 "enginespeed" Numeric( 5, 0 ),
 "fuellevel" Numeric( 5, 0 ),
 "fuelcons" Numeric( 5, 0 ),
 "accelerator" Numeric( 3, 0 ),
 "tachograph" Numeric( 5, 0 ),
 "axleweight" Numeric( 5, 0 ),
 "indicators" Numeric( 10, 0 ),
 "drivercode" Numeric( 20, 0 ),
 "wiretemp1" Double Precision,
 "wiretemp2" Double Precision,
 "wiretemp3" Double Precision,
 "wiretemp4" Double Precision,
 "wiretemp5" Double Precision,
 "wiretemp6" Double Precision,
 "fuelflag" Integer,
 "gsmsignal" SmallInt,
 "speedcan" Integer,
 "gsmoperator" Bigint,
 "totalidlefuel" Bigint,
 "fuellevelperc" Integer,
 "enginetemp" SmallInt,
 "enginetotalhours" Bigint,
 "engineidletime" Bigint,
 "oiltemp" SmallInt,
 "hydroiltemp" SmallInt,
 "wirecode1" Numeric( 20, 0 ),
 "wirecode2" Numeric( 20, 0 ),
 "wirecode3" Numeric( 20, 0 ),
 "wirecode4" Numeric( 20, 0 ),
 "wirecode5" Numeric( 20, 0 ),
 "wirecode6" Numeric( 20, 0 ),
 "rapidpedalpress" Bigint,
 "rapidaccel" Bigint,
 "rapidbreak" Bigint,
 "engineoverspeed" Bigint,
 "torgue" SmallInt,
 "drivetimeoverspeedlimit0x12" Bigint,
 "drivetimeoverspeedlimit0x13" Bigint,
 "driver1idcard" Numeric( 20, 0 ),
 "driver2idcard" Numeric( 20, 0 ),
 "x3d" SmallInt,
 "y3d" SmallInt,
 "z3d" SmallInt,
 "axleweight1" Integer,
 "axleweight2" Integer,
 "axleweight3" Integer,
 "axleweight4" Integer );

1 个答案:

答案 0 :(得分:0)

我建议使用“窗口函数”LEAD()而不是使用MOD()进行自我加入。

SELECT
      d.deviceid       AS deviceid
    , d.ts - d.lead_ts AS roznicaczasu
    , d.ts             AS rozpoczecietrasy
    , d.lead_ts        AS zakonczenietrasy
FROM (
      SELECT
            deviceid
          , ts
          , case when MOD(Inputs,2) = 1
                 then LEAD(ts) OVER (PARTITION BY deviceid, eventid 
                                     ORDER BY inputs DESC)
            end AS lead_ts
      FROM DEVICE_DATA
      WHERE eventid = 11
      ) d
WHERE d.lead_ts IS NOT NULL
;