我遇到了一个生产软件从db服务器上吃掉所有cpu的问题。
软件版本:
硬件(虚拟机):
实际上,这是物理服务器上唯一的虚拟机。 VMware等。
表格:
CREATE TABLE doctable
(
id serial NOT NULL,
lastupdateddate timestamp without time zone,
mycolor character varying(255),
myshade character varying(255),
xmlstuff xml,
CONSTRAINT doctable_pkey PRIMARY KEY (id)
)
实际指数:
CREATE INDEX doctable_shade_color_idx
ON doctable
USING btree
(myshade COLLATE pg_catalog."default", mycolor COLLATE pg_catalog."default");
实际查询:
SELECT XPATH($1, xmlstuff) FROM doctable WHERE myshade = $2 AND mycolor= $3;
索引使用正确,但是像这样每分钟有数百个调用,xpath函数正在占用CPU 100%,从而减慢了服务器的速度。
xml也可以从几千字节到几兆字节。
我在最常用的路径上建立索引,但我不认为可以使用此处的索引。我错了吗?
我无法在接下来的几周内访问来源,而且负载正在增加。有什么我可以做的吗?
磁盘访问非常低,因为所有数据都在ram中。也许为xml设置STORAGE EXTERNAL?
答案 0 :(得分:0)
好吧,正如你所说,SQL部分正常工作,但会发生什么 - 自定义($ 1)XPath表达式在WHERE返回的N行上进行评估。据我所知,postgresql中没有任何内容可以做。解析xml并应用表达式(这可能是任意复杂的)只需要时间。
在我看来,这不是一个非常好的设计,至少表现明智。解决这种情况的一种方法可能是使用最常见的XPath查询和预先计算的结果构建帮助程序表(并以某种方式使其保持最新)。
查询/存储过程看起来像:
SELECT XPathResult From tblHelper WHERE XPathQuery = $1 and myshade = $2 AND mycolor= $3;
只有在未预先计算XPathQuery时才执行它。所有列的索引,但XPathResult我猜,这取决于你的查询。
在doctable
上我将INSERT / UPDATE触发器运行一组最常见的查询并将它们插入到帮助程序表中。当然,你必须在第一次运行一些长期运行的sproc来填充它。
这一切都很糟糕,但目前我还没有看到更好的方法。希望其他人会有更好的想法:)