0

vzla_segは道路のネットワークセグメントです。各セグメントには一般的な方位角があります。私のパラメータcarAzimuthと同じ一般的な方向(+/- 30度)上のセグメントを見つけようとしてCOUNT(*) = 3.849.834このフィルタをsargeableまたはインデックスを改善する方法

CREATE TABLE vzla_seg (`azimuth` int); 

INSERT INTO vzla_seg (`azimuth`) 
VALUES 
    (330), (335), 
    (340), (345), 
    (350), (355), 
    (359), (3), 
    (5),  (15), 
    (20),  (25), 
    (30),  (35) 
; 

イム。

Azimuth範囲は、コンパス度の場合、[0 ..359]です。だから、carAzimuth = 345は方位[315, 325, 359, 0, 5, 15]

carAzimuth = 355 
    segmentAzimuth = 340 --> (355 - 340) -->  15 < 30 
    segmentAzimuth = 359 --> (355 - 359) --> abs(- 4) < 30  
    segmentAzimuth = 20 --> (355 - 20) -->  25 < 30 

carAzimuth = 5 
    segmentAzimuth = 340 --> (5 - 340) --> abs(- 335) > 330  
    segmentAzimuth = 359 --> (5 - 359) --> abs(- 354) > 330  
    segmentAzimuth = 20 --> (5 - 20) --> abs( -15) < 30 

enter image description here

explain analyze 
    SELECT * 
    FROM map.vzla_seg S 
    WHERE 
     abs(carAzimuth - S.azimuth) < 30 
    OR abs(carAzimuth - S.azimuth) > 330 

インデックス付きの道路セグメントと同じ方向にある場合:

CREATE INDEX vzla_seg_azimuth_idx 
    ON map.vzla_seg 
    USING btree 
    (azimuth); 

説明プラン:

"Seq Scan on vzla_seg s (cost=0.00..151243.55 rows=2138790 width=84) 
         (actual time=0.061..14086.038 rows=690334 loops=1)" 
" Filter: ((abs((345 - azimuth)) < 30) OR (abs((345 - azimuth)) > 330))" 
" Rows Removed by Filter: 3159500" 
"Total runtime: 14283.524 ms" 

ボーナス質問:

  • コストがrows=2.138.790言うなぜ総COUNT(*) = 3.849.834
    • と一致Rows Removed by Filter: 3.159.500rows=690.334を言って説明した場合は?
+0

あなたの質問に 'CREATE TABLE'ステートメントといくつかの' INSERT'ステートメントを貼り付けてください。 –

+0

@ MikeSherrill'CatRecall 'あなたはそこからどのような付加情報が必要なのか、 'テーブル作成'が本当に必要ですか?1つのフィールドだけが'方位角整数 'です。たぶん「方位角」は一般的な用語ではないでしょうか? –

+0

postgresql-performanceタグのinfoリンクに従ってください。 –

答えて

1

あなたはより少ない/よりBETWEENおよび/またはそれ以上を使用することができます。これは、インデックスの最適利用を行う場合を参照してください

SELECT * 
    FROM map.vzla_seg S 
    WHERE 
     (S.azimuth BETWEEN (carAzimuth - 30) AND (carAzimuth + 30)) 
    OR S.azimuth < (carAzimuth - 330) 
    OR S.azimuth > (carAzimuth + 330) 
+0

' azimuth'の範囲は円のように '0 ... 359'です。だから '359'の後に再び' 0'で始まる –

+0

また、 '345'は定数ではないパラメータですが、説明付きのパラメータを追加する方法は分かりません:( –

+0

私はそれを考え出しました。あなたのパラメータ名で354を置き換えることができます。リセット角度について何をするべきか分かりません。元のクエリで 'carAzimuth'が359、' S.azimuth'が1だった場合、358の "違い"を得るでしょう。 -2. –

0

SELECT * 
FROM map.vzla_seg S 
WHERE s.azimuth > 315 and s.azimuth < 375; 

もしそうなら、私はその論理が次のようだと思う:

SELECT * 
FROM map.vzla_seg S 
WHERE (s.azimuth > 315 and s.azimuth < 375) or 
     (s.azimuth > 15 and s.azimuth < 30) ; 
これは、インデックスを使用しない場合

は、orの代わりにunion allを使用します。

SELECT * 
FROM map.vzla_seg S 
WHERE (s.azimuth > 315 and s.azimuth < 375) 
UNION ALL 
SELECT * 
FROM map.vzla_seg S 
WHERE (s.azimuth > 15 and s.azimuth < 30) ; 
+0

'azimuth'の範囲は円のように' 0 ... 359'程度です。 –

+0

また、 '345'は定数ではありませんが、どのように説明を伴うパラメータを追加するのかわかりません:( –

1

あなたはこれを試すことができます。

with param(car_azimuth) as (select 345) 
    select * 
    from vzla_seg s, param 
    where 
     s.azimuth > car_azimuth- 30 and 
     s.azimuth < car_azimuth+ 30 or 
     s.azimuth < car_azimuth- 330 or 
     s.azimuth > car_azimuth+ 330; 

計画は、おそらくパラメータが渡されますどのような方法に依存します。定数(100万行)を説明してください:

explain 
    select * 
    from vzla_seg s 
    where 
     s.azimuth > 345- 30 and 
     s.azimuth < 345+ 30 or 
     s.azimuth < 345- 330 or 
     s.azimuth > 345+ 330; 

              QUERY PLAN            
------------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on vzla_seg s (cost=3496.96..11233.44 rows=160405 width=8) 
    Recheck Cond: (((azimuth > 315) AND (azimuth < 375)) OR (azimuth < 15) OR (azimuth > 675)) 
    -> BitmapOr (cost=3496.96..3496.96 rows=165574 width=0) 
     -> Bitmap Index Scan on vzla_seg_azimuth_idx (cost=0.00..2598.70 rows=123828 width=0) 
       Index Cond: ((azimuth > 315) AND (azimuth < 375)) 
     -> Bitmap Index Scan on vzla_seg_azimuth_idx (cost=0.00..773.52 rows=41746 width=0) 
       Index Cond: (azimuth < 15) 
     -> Bitmap Index Scan on vzla_seg_azimuth_idx (cost=0.00..4.43 rows=1 width=0) 
       Index Cond: (azimuth > 675) 
(9 rows)    
+0

私の質問はうまくありませんでしたたとえば、 's.azimuth> 675'は常にfalseです。範囲は[0..359]です。なぜなら、1つのANDだけがsimetricalに見えない理由は分かりません。 '(carAzimuth - roadAzimuth)<0'に依存する計算式が必要であるため、インデックスを使用しないでください。 –

+0

これは' abs'を使ったクエリと正確に等価です。正しいですか? – klin

+0

私はとても恥ずかしいです。あなたは正しく、 '[0 .. 359]'のセグメント値を持つ1つのExcelテーブルを作成し、必要に応じてcarAzimuthとすべての条件一致を変更するセルを作成します。 Dスタンリーと同じですが、私はそれを見ませんでした。 –

関連する問題