在Firebird中执行速度慢

时间:2016-01-07 13:05:23

标签: sql performance firebird

我执行的SQL查询如下:

update elements E
    set E.END_I = (select n.node_num
                   from nodes N 
                   where abs(E.X_I - N.XI) < 0.001 and
                         abs(E.Y_I - N.YI) < 0.001 and
                         abs(E.Z_I - N.ZI) < 0.001
                  )

完成需要大约24秒,我读到关于火鸟故障排除的Why is my database query slow?它指示为表格中的相关字段创建索引,并且我已经添加了XI,YI的递减/递增指数,两个节点和元素表中的ZI字段。但是性能仍然很慢,数据库中有6677行,我使用FlameRobin作为SQL编辑器。

有趣的是:如Firebird故障排除指南所述

  

如果你看到自然计划与大桌子对比,你就找到了   问题

这个错误被描述为坏情况和减速源,推荐的解决方案是,为相关字段创建递减指数。但在我的情况下,即使在定义指数之后,似乎我还在遭受如图所示的Flamerobin输出中报告的PLAN(N NATURAL),PLAN(E NATURAL)。

我该如何消除它?

Preparing query: update elements E set E.END_I = (select n.node_num from nodes N 
where abs(E.X_I-N.XI)<0.001 and abs(E.Y_I - N.YI)<0.001 and abs(E.Z_I-N.ZI)<0.001 )
Prepare time: 0.004s
PLAN (N NATURAL)
PLAN (E NATURAL)

Executing...
Done.
108818273 fetches, 79227 marks, 4050 reads, 9380 writes.
0 inserts, 6677 updates, 0 deletes, 0 index, 14549183 seq.
Delta memory: 212 bytes.
ELEMENTS: 6677 updates. 
6677 rows affected directly.
Total execution time: 24.038s
Script execution finished.

CREATE DESCENDING INDEX IDX_ELEMENTS1 ON ELEMENTS (Z_I);
CREATE DESCENDING INDEX IDX_XI ON ELEMENTS (X_I);
CREATE DESCENDING INDEX IDX_YI ON ELEMENTS (Y_I);
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
 ON ELEMENTS TO  SYSDBA WITH GRANT OPTION;

CREATE DESCENDING INDEX IDX_NODES1_XI ON NODES (XI);
CREATE DESCENDING INDEX IDX_NODES1_YI ON NODES (YI);
CREATE DESCENDING INDEX IDX_NODES1_ZI ON NODES (ZI);
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
 ON NODES TO  SYSDBA WITH GRANT OPTION;

3 个答案:

答案 0 :(得分:2)

abs()函数减慢了查询速度,因为裸列上的索引不能用于表达式。 尝试更改查询以至少为db提供使用索引的机会

update elements E
    set E.END_I = (select n.node_num
                   from nodes N 
                   where N.XI < E.X_I + 0.001 AND N.XI > E.X_I - 0.001
                   AND N.YI < E.Y_I + 0.001 AND N.YI > E.Y_I - 0.001
                   AND N.ZI < E.Z_I + 0.001 AND N.ZI > E.Z_I - 0.001
                  )

答案 1 :(得分:0)

在列X_I,Y_I,Z_I上创建索引,然后运行语句:

MERGE INTO elements dst
   USING (
    SELECT e.x_i, e.y_i, e.z_i, n.node_num
    FROM nodes N JOIN elements E ON 
      abs(E.X_I - N.XI) < 0.001 and
      abs(E.Y_I - N.YI) < 0.001 and
      abs(E.Z_I - N.ZI) < 0.001
   ) src
ON dst.X_I = src.X_I AND dst.Y_I = src.Y_I AND dst.Z_I = src.Z_I
WHEN MATCHED THEN UPDATE SET dst.END_I = src.NODE_NUM

正如答案https://stackoverflow.com/a/34656659/55350所述,您可以摆脱ABS功能,并在N表的第XI,YI,ZI列上创建索引,以进一步加快流程。

答案 2 :(得分:0)

也许这样的事情会有所帮助:

1)在表格之间创建笛卡尔积,计算X,Y和Z。

2)过滤所需的记录。

3)使用node_num值更新元素记录。

expression = (x => x.PersonGroups.Any(y => y.Group.GroupType == null || y.Group.GroupType == "")); 
return expression
相关问题