Firebird在ORDER BY时性能下降

时间:2015-01-04 03:33:18

标签: performance devexpress firebird xtragrid

我有一个名为VW_PURCHASE_ORDER_LIST的视图。它总共有大约200,000条记录。

运行查询需要16ms:

select first 128 * from VW_PURCHASE_ORDER_LIST 

然而,当我使用order by语句时,它需要更长的时间......大约9s

select first 128 * from VW_PURCHASE_ORDER_LIST
order by id asc

Plan
PLAN SORT (JOIN (VW_PURCHASE_ORDER_LIST LEVY BT NATURAL, VW_PURCHASE_ORDER_LIST M INDEX (PK_MATTER), VW_PURCHASE_ORDER_LIST LEVY F INDEX (PK_B_BUDGET_LEVY_FREQUENCY), VW_PURCHASE_ORDER_LIST BT_FHC INDEX (PK_BT_FINANCIAL_HEALTH_CHECK), VW_PURCHASE_ORDER_LIST BD INDEX (PK_BT_BUILDING_DETAILS), VW_PURCHASE_ORDER_LIST USR_STRATAMANAGER INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST POH INDEX (FK_PURCHASE_ORDER_HEADER_1), VW_PURCHASE_ORDER_LIST PS INDEX (PK_LK_PO_PAID_STATUS), VW_PURCHASE_ORDER_LIST POS INDEX (PK_LK_PURCHASE_ORDER_STATUS), VW_PURCHASE_ORDER_LIST LM INDEX (UNQ1_P_ORDER_MODIFIED_DATE), VW_PURCHASE_ORDER_LIST SUPPLIER INDEX (PK_CONTACT), VW_PURCHASE_ORDER_LIST USR_CREATED INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST USR_MODIFIED INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST USR_APPROVED INDEX (PK_USER_DETAIL)))

------ Performance info ------
Prepare time = 32ms
Execute time = 8s 80ms
Avg fetch time = 237.65 ms
Current memory = 98,671,784
Max memory = 99,258,368
Memory buffers = 2,048
Reads from disk to cache = 230,443
Writes from cache to disk = 0
Fetches from cache = 6,253,743

有没有办法加快速度?问题是我们的数据库规模在不断扩大,现在有很多大型表。我们的应用程序用于将整个表加载到网格中,但由于我们现在拥有如此多的数据,因此需要几分钟才能加载并最大化客户端PC的RAM。

作为解决方案,我们使用的是DevExpress ServerMode XtraGrid。在网格上加载和滚动很慢,因为它正在发送初始select count(*) from x_table_or_view_name以获取总记录,然后在滚动时发送select first x skip y from x_table_or_view_name order by id ....这样的顺序会减慢查询的速度。使网格无法使用

我不知道从哪里开始,因为我不是数据库专家,如果有人可以提供一些建议,我们将不胜感激。

无订单更新:

select first 128 * from VW_PURCHASE_ORDER_LIST

Plan
PLAN JOIN (VW_PURCHASE_ORDER_LIST LEVY BT NATURAL, VW_PURCHASE_ORDER_LIST M INDEX (PK_MATTER), VW_PURCHASE_ORDER_LIST LEVY F INDEX (PK_B_BUDGET_LEVY_FREQUENCY), VW_PURCHASE_ORDER_LIST BT_FHC INDEX (PK_BT_FINANCIAL_HEALTH_CHECK), VW_PURCHASE_ORDER_LIST BD INDEX (PK_BT_BUILDING_DETAILS), VW_PURCHASE_ORDER_LIST USR_STRATAMANAGER INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST POH INDEX (FK_PURCHASE_ORDER_HEADER_1), VW_PURCHASE_ORDER_LIST PS INDEX (PK_LK_PO_PAID_STATUS), VW_PURCHASE_ORDER_LIST POS INDEX (PK_LK_PURCHASE_ORDER_STATUS), VW_PURCHASE_ORDER_LIST LM INDEX (UNQ1_P_ORDER_MODIFIED_DATE), VW_PURCHASE_ORDER_LIST SUPPLIER INDEX (PK_CONTACT), VW_PURCHASE_ORDER_LIST USR_CREATED INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST USR_MODIFIED INDEX (PK_USER_DETAIL), VW_PURCHASE_ORDER_LIST USR_APPROVED INDEX (PK_USER_DETAIL))

------ Performance info ------
Prepare time = 16ms
Execute time = 15ms
Avg fetch time = 0.44 ms
Current memory = 36,398,384
Max memory = 0
Memory buffers = 2,048
Reads from disk to cache = 172
Writes from cache to disk = 0
Fetches from cache = 2,654

这是下面的实际视图。如果这有帮助,我可以在联接中为表格发布DDL吗?

CREATE VIEW VW_PURCHASE_ORDER_LIST(
    ID,
    ID_BUILDING,
    ID_SUPPLIER,
    ID_STATUS,
    ID_USER_CREATED,
    ID_USER_MODIFIED,
    DATE_ORDER,
    DATE_CREATED,
    DATE_MODIFIED,
    DATE_PAYMENT_COMMITMENT,
    ISARCHIVED,
    JOURNAL,
    NOTES,
    PO_NUMBER,
    SUPPLIER_INVOICE_NUMBER,
    TERMS_IN_DAYS,
    STRATA_PLAN_NUMBER,
    BUILDING_DISPLAY,
    SUPPLIER_DISPLAY,
    USERNAME_CREATED,
    USERNAME_MODIFIED,
    STATUS_DESCRIPTION,
    ID_USER_APPROVED,
    USERNAME_APPROVED,
    ID_STRATA_MANAGER,
    USERNAME_STRATAMANAGER,
    DATE_LATEST_PAYMENT_BANKED,
    INSURANCE_PREMIUM,
    NEXT_DATE_RENEWAL,
    COUNT_UNALLOCATED_BANK_TRANS,
    SUM_UNALLOCATED_BANK_TRANS,
    LIST_PAYMENT_TRANS_TYPE,
    LIST_PAYMENT_ACCOUNT,
    LIST_PAYMENT_NUMBER,
    ID_PAID_STATUS,
    PAID_STATUS_DESC,
    LIST_DEBIT_ACCOUNTS,
    LIST_DETAIL_AMOUNT,
    ADMIN_LEVY_YEAR_END_DATE,
    LEVY_ARREARS,
    NEXT_ADMIN_LEVY_DATE,
    ADMIN_LEVY_FREQUENCY,
    PAYABLE_NOTES)
AS
select
  poh.id,
  poh.id_building,
  poh.id_supplier,
  poh.id_status,
  poh.id_user_created,
  poh.id_user_modified,
  poh.date_order,
  poh.date_created,
  MAXVALUE(lm.date_modified, levy.modified_date, bd.modified_date),
  poh.date_payment_commitment,
  poh.isarchived,
  poh.journal,
  poh.notes,
  poh.order_number,
  poh.supplier_invoice_number,
  poh.terms_in_days,
  m.matter_code,
  m.matter_display,
  supplier.contact_display,
  usr_created.user_name,
  usr_modified.user_name,
  pos.description,
  poh.id_user_approved,
  usr_approved.user_name,
  bd.id_strata_manager,
  usr_stratamanager.user_name,
  poh.date_latest_payment_banked,
  m.sum_insurance_premium,
  m.next_date_renewal,
  bt_fhc.count_unallocated_bank_trans,
  bt_fhc.sum_unallocated_bank_trans,
  lm.list_payment_trans_type,
  lm.list_payment_account,
  lm.list_payment_number,
  poh.id_paid_status,
  ps.description,
  lm.list_debit_accounts,
  lm.list_detail_amount,
  levy.admin_levy_year_end_date,
  levy.levy_arrears,
  levy.next_admin_levy_date,
  levy.admin_frequency,
  bd.payable_notes
from purchase_order_header poh
join purchase_order_modified_date lm on lm.id_purchase_order = poh.id
join lk_purchase_order_status pos on pos.id = poh.id_status
join matter m on m.matter_id = poh.id_building
join contact supplier on supplier.contact_id = poh.id_supplier
join user_detail usr_created on usr_created.user_id = poh.id_user_created
join user_detail usr_modified on usr_modified.user_id = poh.id_user_modified
join user_detail usr_approved on usr_approved.user_id = poh.id_user_approved
join bt_building_details bd on bd.id = m.matter_id
join user_detail usr_stratamanager on usr_stratamanager.user_id = bd.id_strata_manager
join BT_FINANCIAL_HEALTH_CHECK bt_fhc on bt_fhc.id = poh.id_building
join lk_po_paid_status ps on ps.id = poh.id_paid_status
join VW_BT_LEVY levy on levy.Id = poh.id_building
where poh.id <> 0
;

1 个答案:

答案 0 :(得分:1)

我知道这是一个非常老的问题,但是由于有很多反对意见,所以我认为这是一个普遍的问题。从2.5迁移到3.0后,我也遇到了这个问题,我发现的解决方案非常简单。就您而言:

order by  id || '' asc

或者,如果id是数字:

order by id + 0 asc

可能的解释:

Firebird 3尝试尽可能使用现有索引来产生排序。当结果集仅占数据库的一小部分时,将是有害的。呈现的表达式不会更改顺序键值,但会“欺骗”数据库优化器,并且不使用索引。