Postgresql从表性能与MySql中选择*

时间:2009-12-18 01:22:23

标签: mysql performance postgresql

我有一个MySQL数据库,我正在移植到PostgreSQL(因为GIS功能)。

许多表都有数十万行,所以我需要牢记性能。

我的问题是PostgreSQL似乎非常慢......

例如,如果我在MySQL数据库中的特定表上执行一个简单的SELECT * FROM [table],假设有一个113,000行,查询大约需要2秒钟来返回数据。 在PostgreSQL中,同一个表上完全相同的查询大约需要10秒钟。

同样,我有另一张表格,行数较少(88,000),而且情况更糟! MySQL需要1.3秒,PostgreSQL需要30秒!

这是我对PostgreSQL的期望,还是我能做些什么才能让它变得更好?

我的操作系统是XP,我正在运行一个带有3GB内存的2.7ghz双代码。 MySQL数据库是5.1版,运行库存标准。 PostgreSQL数据库是版本8.4,我编辑了如下配置: shared_buffers = 128MB effective_cache_size = 512MB

谢谢!

这是第二个表的结构,它有大约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语句玩了一下。如果我只是“从NodeLink中选择NodeLinkID”,查询会更快 - 不到一秒就能得到88,000行。 如果我“选择NodeLinkID,从NodeLink中删除”,查询需要很长时间 - 大约8秒。 这是否能说明我做错了什么?


更多调查结果:

  

创建INDEX节点linklink_lengthIDX   nodelink(长度);

     

分析nodelink

     

- 执行查询:SELECT * FROM nodelink WHERE Length BETWEEN 0 AND   3.983总查询运行时间: 3109 ms。检索到10000行。

     

- 执行查询:SELECT nodelinkID FROM nodelink WHERE Length BETWEEN 0   AND 3.983总查询运行时: 125   ms。检索到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]

因此结果具有可比性。 似乎postgreSQL附带的pgadmin工具非常慢。 感谢大家的建议和帮助!

mjy,如果你想发一个答案,我可以把它作为正确的答案,以备将来参考。

6 个答案:

答案 0 :(得分:2)

关于调整Postgres的

Here is a useful article - 它有定义和一些提示。

This performance tuning article提供了一个相当不错的概述,其中包含一些具体的优化方法。

答案 1 :(得分:1)

您是否也拥有MySQL中的GIS功能? IIRC,这意味着您使用的是MyISAM而不是具有交易功能的存储管理器,这意味着您实际上并不是在比较苹果和苹果。

此外,您的应用程序是否真的会这样做?所有行的完全不合格的SELECT?如果没有,你更好地看看你实际将要做的事情的表现,这可能至少涉及WHERE条款。 (虽然这当然也不能与非崩溃安全非交易系统相比)

答案 2 :(得分:0)

PostgreSQL使用MVCC架构,这意味着它使用比MySQL更复杂的格式存储数据。单一访问速度较慢,多用户访问速度较快。

a)检查您的表是否已抽真空 - 查看VACUUM语句 b)使用索引 - PostgreSQL有比MySQL更大的索引库,所以使用它 - 有GiST,GIN索引。

答案 3 :(得分:0)

听起来像是受到了碎片的影响。没有真空吸尘器,你有很多更新吗?您是否更新了索引列,因此未使用HOT更新?

select relpages, reltuples from pg_class where relname='nodelink'的输出是什么。这将显示您的元组存储的磁盘页数。

@Pavel:PostgreSQL当然更灵活。索引,但索引在这种情况下无济于事,因为他正在选择表中的所有内容。

  

许多表都有数十万行,所以我需要牢记性能。

这些不是特别大的表......

  

这是我对PostgreSQL的期望,还是我能做些什么才能让它变得更好?

...所以你可能还有别的错误。

答案 4 :(得分:0)

如果您的表有数百个(更不用说数十万个)记录,那么您有什么理由可以运行查询SELECT * FROM?也许您应该考虑一下您实际查询的数据,以及如何从数据库中获取相关的行。

答案 5 :(得分:0)

对于普通的100000行表来说,这要长得多,所以我认为PostGIS中存在问题,而不是PostgreSQL。尝试获取没有shapenative和shapewgs84列的所有行 - 如果它更快,那么看起来像PostGIS负责减速。