如何使此过滤器可搜索或提高索引
How make this filter sargeable or improve index
vzla_seg
为路网段。每一段都有他的大致方位角。 COUNT(*) = 3.849.834
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)
;
我试图在与我的参数 carAzimuth
相同的大体方向(+/- 30 度)上找到线段。
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
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 Removed by Filter: 3.159.500
和 rows=690.334
匹配总数 COUNT(*) = 3.849.834
- 为什么费用说
rows=2.138.790
?
您可以使用 BETWEEN
和/或大于 than/less:
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)
看看这是否优化了索引的使用:
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) ;
如果不使用索引,请使用 union all
而不是 or
:
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) ;
你可以试试这个:
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)
vzla_seg
为路网段。每一段都有他的大致方位角。 COUNT(*) = 3.849.834
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)
;
我试图在与我的参数 carAzimuth
相同的大体方向(+/- 30 度)上找到线段。
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
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 Removed by Filter: 3.159.500
和rows=690.334
匹配总数COUNT(*) = 3.849.834
- 为什么费用说
rows=2.138.790
?
- 为什么费用说
您可以使用 BETWEEN
和/或大于 than/less:
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)
看看这是否优化了索引的使用:
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) ;
如果不使用索引,请使用 union all
而不是 or
:
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) ;
你可以试试这个:
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)