I'm using PostgreSQL 9.6 and have the following table:
CREATE TABLE eco.tracks (
id bigserial NOT NULL,
time_track timestamp NOT NULL,
track bigint ,
distance_1 int ,
CONSTRAINT pk_tracks PRIMARY KEY ( id )
);
And I manipulate data it contains with a very simple query:
SELECT (track, distance_1, time_track)
FROM eco.tracks
WHERE time_track - (%s) <= INTERVAL '10 seconds'
AND (%s)-time_track <= INTERVAL '10 seconds'
AND distance_1 IS NOT NULL
ORDER BY distance_1 asc LIMIT 1;
Some inputs:
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (23467, '2018-05-18 20:43:06', 386, 17965);
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (23468, '2018-05-18 20:43:07', 386, 18168);
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (23469, '2018-05-18 20:43:08', 386, 18168);
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (22974, '2018-05-18 20:40:07', 376, 8394);
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (22968, '2018-05-18 20:40:00', 376, 9051);
INSERT INTO tracks (id, time_track, track, distance_1) VALUES (22837, '2018-05-18 20:39:17', 366, 13133);
This query is used to take the closest track number & other two params in range of setted time +- 10sec. But in my system, this one is a bottleneck, is it possible to improve it?
I've tried to play around with value work_mem
, no success.
Actually, I use it for checking like if-else. And then make another query.
Can I merge it?
SELECT (track, distance_1, aircraft_time)
FROM eco.tracks WHERE time_track - (%s) <= INTERVAL '10 seconds' and (%s)-time_track <= INTERVAL '10 seconds' ORDER BY distance_1 asc LIMIT 1,
CASE track WHEN NOT NULL THEN
(
INSERT INTO eco.noise (
time_noise, track, distance, aircraft_time)
VALUES (%s, track, distance_1, aircraft_time) ON CONFLICT DO NOTHING;
)
OR
WITH check_1 AS
(SELECT track, distance_1, aircraft_time FROM eco.tracks
WHERE time_track - (%s) <= INTERVAL '10 seconds' and (%s)-time_track <= INTERVAL '10 seconds' ORDER BY distance_1 asc LIMIT 1)
INSERT INTO eco.noise (time_noise, track, distance, aircraft_time)
VALUES (%s, check_1.track, check_1.distance_1, check_1.aircraft_time)
WHERE
check_1.track IS NOT NULL ON CONFLICT DO NOTHING;
)
Note: I use it in Python 3 by using psycopg2.
Best Answer
assuming you have an index on time_track
move the offsets to the other side of the inequality so that the arithmetic is only done once and so that an index on time_track can be used.
etc...
or you could use
BETWEEN
instead of and.