簡體   English   中英

在Firebird中執行速度慢

[英]Slow query execution in 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秒才能完成,我讀到了關於firebird故障排除為什么我的數據庫查詢速度慢? 它指示為表中的相關字段創建索引,並且我在兩個節點和元素表中添加了XI,YI,ZI字段的遞減/遞增索引。 但是性能仍然很慢,數據庫中有6677行,我使用FlameRobin作為SQL編輯器。

有趣的是:正如Firebird故障排除指南所描述的那樣

如果您看到自然計划與大桌面對比,您就會發現問題所在

這個錯誤被描述為壞情況和減速源,推薦的解決方案是,為相關字段創建遞減指數。 但在我的情況下,即使在定義指數之后,似乎我仍然受到計划(N NATURAL),PLAN(E NATURAL)的影響,這在Flamerobin輸出中報告如下所示。

我怎么能消除那個?

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;

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
                  )

在列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列上創建索引,以進一步加快進程。

也許這樣的事情可以幫助:

1)在表格之間創建笛卡爾積,計算X,Y和Z.

2)過濾所需的記錄。

3)使用node_num值更新元素記錄。

execute block
as
declare variable key integer; -- primary key type
declare variable node_num integer; -- node_num type
begin
  for
    select
      key,
      node_num
    from (
      select
        E.key, -- primary key name
        N.node_num,
        abs(E.X_I - N.XI) as X,
        abs(E.Y_I - N.YI) as Y,
        abs(E.Z_I - N.ZI) as Z
      from elements E, nodes N)
    where (X < 0.001)
      and (Y < 0.001)
      and (Z < 0.001)
    into
      :key,
      :node_num
  do
  begin
    update elements set
      END_ID = :node_num
    where elements.key = :key; -- primary key name
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM