У меня есть база данных MySQL, которую я портирую на PostgreSQL (из-за особенностей ГИС).
Многие таблицы содержат сотни тысяч строк, поэтому мне нужно помнить о производительности.
Моя проблема в том, что PostgreSQL кажется ужасно медленным ...
Например, если я сделаю простой SELECT * FROM [таблица] для определенной таблицы в базе данных MySQL, скажем, в той, которая имеет 113 000 строк, запросу потребуется около 2 секунд для возврата данных.
В PostgreSQL точно такой же запрос к той же таблице занимает почти 10 секунд.
Точно так же у меня есть другая таблица с меньшим количеством строк (88 000), и она хуже! MySQL занимает 1,3 секунды, PostgreSQL - 30 секунд!
Это то, что я могу ожидать от PostgreSQL, или я могу что-то сделать, чтобы сделать его лучше?
Моя ОС - XP, и я использую 2,7 ГГц двойной код с оперативной памятью 3 ГБ.
База данных MySQL - версия 5.1, стандартная комплектация.
База данных PostgreSQL - версия 8.4, и я отредактировал конфигурацию следующим образом:
shared_buffers = 128 МБ
ffective_cache_size = 512 МБ
Спасибо!
Вот структура второй таблицы, которая содержит около 88 000 строк:
CREATE TABLE nodelink
(
nodelinkid serial NOT NULL,
workid integer NOT NULL,
modifiedbyid integer,
tabulardatasetid integer,
fromnodeid integer,
tonodeid integer,
materialid integer,
componentsubtypeid integer,
crosssectionid integer,
"name" character varying(64) NOT NULL,
description character varying(256) NOT NULL,
modifiedbyname character varying(64) NOT NULL, -- Contains the values from the old engine's ModifiedBy field, since they don't link with any user
linkdiameter double precision NOT NULL DEFAULT 0, -- The diameter of the Link
height double precision NOT NULL,
width double precision NOT NULL,
length double precision NOT NULL,
roughness double precision NOT NULL,
upstreaminvert double precision NOT NULL,
upstreamloss double precision NOT NULL,
downstreaminvert double precision NOT NULL,
downstreamloss double precision NOT NULL,
averageloss double precision NOT NULL,
pressuremain double precision NOT NULL,
flowtogauge double precision NOT NULL,
cctvgrade double precision NOT NULL,
installdate timestamp without time zone NOT NULL,
whencreated timestamp without time zone NOT NULL,
whenmodified timestamp without time zone NOT NULL,
ismodelled boolean NOT NULL,
isopen boolean NOT NULL,
shapenative geometry,
shapewgs84 geometry,
CONSTRAINT nodelink_pk PRIMARY KEY (nodelinkid),
CONSTRAINT componentsubtype_nodelink_fk FOREIGN KEY (componentsubtypeid)
REFERENCES componentsubtype (componentsubtypeid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT crosssection_nodelink_fk FOREIGN KEY (crosssectionid)
REFERENCES crosssection (crosssectionid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fromnode_nodelink_fk FOREIGN KEY (fromnodeid)
REFERENCES node (nodeid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT material_nodelink_fk FOREIGN KEY (materialid)
REFERENCES material (materialid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT tabulardataset_nodelink_fk FOREIGN KEY (tabulardatasetid)
REFERENCES tabulardataset (tabulardatasetid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT tonode_nodelink_fk FOREIGN KEY (tonodeid)
REFERENCES node (nodeid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT user_nodelink_fk FOREIGN KEY (modifiedbyid)
REFERENCES awtuser (userid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT work_modellink_fk FOREIGN KEY (workid)
REFERENCES "work" (workid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE nodelink OWNER TO postgres;
COMMENT ON TABLE nodelink IS 'Contains all of the data that describes a line between any two nodes.';
COMMENT ON COLUMN nodelink.modifiedbyname IS 'Contains the values from the old engine''s ModifiedBy field, since they don''t link with any user';
COMMENT ON COLUMN nodelink.linkdiameter IS 'The diameter of the Link';
Я играл немного больше с оператором select. Если я просто сделаю «Выбрать NodeLinkID из NodeLink» , запрос будет выполняться намного быстрее - менее секунды, чтобы получить 88 000 строк.
Если я сделаю «Выбрать NodeLinkID, shapenative от NodeLink» , запрос займет много времени - около 8 секунд.
Это проливает свет на то, что я делаю неправильно?
Дополнительные выводы:
CREATE INDEX nodelink_lengthIDX on
nodelink (длина);
проанализировать нодлинк
- Выполнение запроса: SELECT * FROM nodelink, ГДЕ ДЛИНА МЕЖДУ 0 И
3.983 Общее время выполнения запроса: 3109 мс. 10000 найденных строк.
- Выполнение запроса: ВЫБЕРИТЕ nodelinkID FROM nodelink WHERE Длина МЕЖДУ 0
AND 3.983 Общее время выполнения запроса: 125
мс. 10000 найденных строк.
В MySQL первый запрос выполняется за 120 мс, второй - за 0,02 мс.
Решение вопроса:
Ну, ребята, похоже, что в стакане воды был шторм ...
MJY было правильно:
" Как вы измерили эти значения времени - в вашем приложении или в соответствующих интерфейсах командной строки? "
Чтобы проверить эту теорию, я собрал простое консольное приложение, которое выполняло тот же запрос на базе данных MySQL, и базу данных PGSQL. Вот вывод:
Running MySQL query: [SELECT * FROM l_model_ldata]
MySQL duration = [2.296875]
Running PGSQL query: [SELECT * FROM nodelink]
PGSQL duration = [2.875]
Так что результаты сопоставимы.
Кажется, что инструмент pgadmin, который поставляется с postgreSQL, работает довольно медленно.
Спасибо всем за их предложения и помощь!
mjy, если вы хотите опубликовать ответ, я могу отметить его как правильный ответ для дальнейшего использования.