Действительно длительный запрос при использовании заказа - PullRequest
1 голос
/ 22 марта 2011

У меня есть серьезная проблема с одним из моих запросов:

SELECT tpostime, gispoint 
FROM mytable 
WHERE idterminal = 233463 
ORDER BY idpos DESC

Когда idterminal не существует в «mytable», этот запрос обрабатывается вечно, а затем мне предоставляется тайм-аут (хорошо, «отмена оператора из-за сообщения запроса пользователя», но когда я удаляю заказ) по предложению все вроде нормально. Теперь мне интересно - idpos является первичным ключом для «mytable», поэтому он проиндексирован, поэтому, я думаю, упорядочение по нему должно быть быстрым. И что важно - «mytable» весит 3Гб.

Таблица и определения индекса:

CREATE TABLE mytable ( 
  idpos serial NOT NULL, 
  tpostime timestamp(0) without time zone, 
  idterminal integer DEFAULT 0, 
  gispoint geometry, 
  idtracks integer, 
  CONSTRAINT mytable_pkey PRIMARY KEY (idpos), 
  CONSTRAINT qwe FOREIGN KEY (idtracks) REFERENCES qwe (idtracks) 
    MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE, 
  CONSTRAINT abc FOREIGN KEY (idterminal) REFERENCES abc (idterminal)
    MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE, 
  CONSTRAINT enforce_geotype_gispoint 
    CHECK (geometrytype(gispoint)= 'POINT'::text OR gispoint IS NULL), 
  CONSTRAINT enforce_srid_gispoint CHECK (srid(gispoint) = 4326)
) WITH OIDS; 

CREATE INDEX idx_idterminal ON mytable USING btree (idterminal); 
CREATE INDEX idx_idtracks ON mytable USING btree (idtracks); 
CREATE INDEX idx_idtracks_idterminal ON mytable USING btree (idtracks, idterminal);

Ответы [ 2 ]

5 голосов
/ 22 марта 2011

Мне кажется, что селективность idterminal достаточно низкая, чтобы Postgres мог выбрать полное сканирование mytable_pkey, а не стоимость заказа всех строк с idterminal = 233463

Я предлагаю:

CREATE INDEX idx_idterminal2 ON mytable USING btree (idterminal, idpos);

и, возможно:

DROP INDEX idx_idterminal;

Вы не упоминаете, является ли это производственной базой данных или нет - если это, конечно, вам нужно сначала проверить влияние изменения в другом месте.

Если вы предпочитаете не менять схему, вы можете попытаться обмануть оптимизатор по пути, который, как вы знаете, лучше всего подходит для чего-то вроде (не проверено) для 8.4 и выше:

SELECT * 
FROM ( SELECT tpostime, gispoint, idpos, row_number() over (order by 1)
       FROM mytable 
       WHERE idterminal = 233463 )
ORDER BY idpos DESC;

или, может быть, просто:

SELECT * 
FROM ( SELECT tpostime, gispoint, idpos
       FROM mytable 
       WHERE idterminal = 233463
       GROUP BY tpostime, gispoint, idpos )
ORDER BY idpos DESC;

или даже:

SELECT tpostime, gispoint 
FROM mytable 
WHERE idterminal = 233463 
ORDER BY idpos*2 DESC
0 голосов
/ 22 марта 2011

У вас есть индекс на idterminal?Попробуйте добавить составной индекс с обоими (idpos, idterminal).Что, вероятно, происходит, если вы выполняете план объяснения, это сначала упорядочение по idpos, а затем сканирование, чтобы найти idterminal.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...