Postgresql Select * из таблицы производительности против MySql - PullRequest
6 голосов
/ 18 декабря 2009

У меня есть база данных 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, если вы хотите опубликовать ответ, я могу отметить его как правильный ответ для дальнейшего использования.

Ответы [ 6 ]

2 голосов
/ 18 декабря 2009

Вот полезная статья о настройке Postgres - в ней есть определения и несколько советов.

Эта статья о настройке производительности предлагает довольно неплохой обзор с некоторыми специфическими методами оптимизации.

1 голос
/ 19 декабря 2009

Были ли у вас функции ГИС в MySQL? IIRC, это означает, что вы использовали MyISAM, а не менеджер хранилища с поддержкой транзакций, что означает, что вы действительно не сравниваете яблоки с яблоками.

Кроме того, ваше приложение будет когда-либо делать это? Совершенно неквалифицированный SELECT из всех строк? Если нет, вам лучше посмотреть на производительность вещей, которые вы на самом деле собираетесь делать, что, вероятно, будет включать, по крайней мере, предложения WHERE. (хотя это, конечно, также нельзя сравнивать с безаварийной нетранзакционной системой)

0 голосов
/ 19 декабря 2009

Это слишком много для обычной таблицы с 100000 строками, поэтому я думаю, что есть проблема в PostGIS, а не в PostgreSQL. Попробуйте получить все строки без столбцов shapenative и shapewgs84 - если это намного быстрее, то похоже, что PostGIS отвечает за замедления.

0 голосов
/ 19 декабря 2009

Если у вас есть таблица с сотнями (не говоря уже о сотнях тысяч) записей, какова возможная причина для выполнения запроса SELECT * FROM? Возможно, вам следует подумать о том, какие данные вы на самом деле запрашиваете, и как вы можете получить только соответствующие строки из базы данных.

0 голосов
/ 18 декабря 2009

Похоже, вы страдаете от фрагментации. У вас много обновлений без запуска вакуума? Обновляете ли вы индексированные столбцы, чтобы HOT-обновления не использовались?

Какой вывод select relpages, reltuples from pg_class where relname='nodelink'. Это покажет вам, на скольких дисковых страницах хранятся ваши кортежи.

@ Павел: PostgreSQL, безусловно, более гибок в отношении. индексы, но индекс не поможет в этом случае, так как он выбирает все в таблице.

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

Это не особо большие столы ...

Это то, что я могу ожидать от PostgreSQL, или я могу что-то сделать, чтобы сделать его лучше?

... так что, вероятно, что-то еще вы делаете неправильно.

0 голосов
/ 18 декабря 2009

PostgreSQL использует архитектуру MVCC, что означает, что он использует более сложный формат для хранения данных на диске, чем MySQL. Это медленнее в одиночном доступе и быстрее в многопользовательском доступе.

а) проверьте, не опустошены ли ваши таблицы - посмотрите инструкцию VACUUM б) использовать индексы - PostgreSQL имеет больший набор индексов, чем MySQL, так что используйте его - есть индексы GiST, GIN.

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