firebird icon indicating copy to clipboard operation
firebird copied to clipboard

OuterJoinConversion = true (i.e. default) causes performance regression since 5.0.1.1416-b4b3559

Open pavel-zotov opened this issue 8 months ago • 0 comments

Performance regression has encountered when comparing snapshots

  • 5.0.1.1416-ad0e5ce (13.06.2024 20:14) == vs==
  • 5.0.1.1416-b4b3559 (17.06.2024 10:21) (and further 5.x up to fresh 5.0.3).

These two snapshots and demo database are uploaded to: https://drive.google.com/drive/folders/19PiXH3MJWU7dw9Vm4uFh0ZznaKZ4aOpY?usp=sharing (database was encrypted, password will be sent privately to firebird2 at yandex.ru)

To reproduce:

  • unpack DB (this is .fbk) and restore it in any 5.0.1 build;
  • Unpack snapshot 5.0.1.1416-ad0e5ce (13.06.2024 20:14)
  • run trace with config:
database =
{
    enabled = true
    log_initfini = false
    log_errors = true
    include_filter = "%(from clrefdet)%"
    time_threshold = 0
    log_statement_finish = true
    explain_plan = true
    print_plan = true
    print_perf = true
    max_sql_length = 32000
    max_arg_length = 32000
    max_arg_count =  10
}
  • set in firebird.conf: OuterJoinConversion = false
  • run query:
set list on;
select * from rdb$config where rdb$config_name = 'OuterJoinConversion';
set count on;
select r.ctdid
from clrefdet r
left join get_usl_struct(iif (r.fact_schid > 0,r.fact_schid, r.schid), '01.01.2026') gs on 1=1
inner join wschema w on w.schid = gs.schid and w.structid = 1
left join clreferrals r2 on r.refid = r2.refid
where
    r.refid = 123804997
    and (r.notuse is null or r.notuse =0)
order by r.rowcode
;

Output will appear almost instantly and will contain 12 records. On this snapshot (5.0.1.1416-ad0e5ce) trace shows:

Select Expression
    -> Sort (record length: 164, key length: 12)
        -> Filter
            -> Nested Loop Join (outer)
                -> Nested Loop Join (inner)
                    -> Filter
                        -> Nested Loop Join (outer)
                            -> Filter
                                -> Table "CLREFDET" as "R" Access By ID
                                    -> Bitmap
                                        -> Index "CLREFDET_REFID" Range Scan (full match)
                            -> Procedure "GET_USL_STRUCT" as "GS" Scan
                    -> Filter
                        -> Table "WSCHEMA" as "W" Access By ID
                            -> Bitmap
                                -> Index "PK_WSCHEMA" Unique Scan
                -> Filter
                    -> Table "CLREFERRALS" as "R2" Access By ID
                        -> Bitmap
                            -> Index "PK_CLREFERRALS" Unique Scan
12 records fetched
      7 ms, 9 read(s), 114 fetch(es)

Table                              Natural     Index    Update    Insert    Delete   Back
*****************************************************************************************
WSCHEMA                                           12
CLREFERRALS                                       12
CLREFDET                                          12

Now let's change in firebird.conf OuterJoinConversion = true (i.e. set it to default value)

Output also will appear very fast, and trace will show:

Select Expression
    -> Filter
        -> Nested Loop Join (outer)
            -> Filter (preliminary)
                -> Sort (record length: 140, key length: 12)
                    -> Nested Loop Join (inner)
                        -> Filter
                            -> Table "CLREFDET" as "R" Access By ID
                                -> Bitmap
                                    -> Index "CLREFDET_REFID" Range Scan (full match)
                        -> Nested Loop Join (inner)
                            -> Procedure "GET_USL_STRUCT" as "GS" Scan
                            -> Filter
                                -> Table "WSCHEMA" as "W" Access By ID
                                    -> Bitmap
                                        -> Index "PK_WSCHEMA" Unique Scan
            -> Filter
                -> Table "CLREFERRALS" as "R2" Access By ID
                    -> Bitmap
                        -> Index "PK_CLREFERRALS" Unique Scan
12 records fetched
      7 ms, 9 read(s), 114 fetch(es)

Table                              Natural     Index    Update    Insert    Delete
*************************************************************************************
WSCHEMA                                           12
CLREFERRALS                                       12
CLREFDET                                          12

####################################################################

Now stop FB and unpack next snapshot, 5.0.1.1416-b4b3559 (17.06.2024 10:21) and repeat above mentioned steps.

  • for OuterJoinConversion = false query runs instantly and trace will show:
Select Expression
    -> Sort (record length: 164, key length: 12)
        -> Filter
            -> Nested Loop Join (outer)
                -> Nested Loop Join (inner)
                    -> Filter
                        -> Nested Loop Join (outer)
                            -> Filter
                                -> Table "CLREFDET" as "R" Access By ID
                                    -> Bitmap
                                        -> Index "CLREFDET_REFID" Range Scan (full match)
                            -> Procedure "GET_USL_STRUCT" as "GS" Scan
                    -> Filter
                        -> Table "WSCHEMA" as "W" Access By ID
                            -> Bitmap
                                -> Index "PK_WSCHEMA" Unique Scan
                -> Filter
                    -> Table "CLREFERRALS" as "R2" Access By ID
                        -> Bitmap
                            -> Index "PK_CLREFERRALS" Unique Scan
12 records fetched
      7 ms, 9 read(s), 114 fetch(es)

Table                              Natural     Index    Update    Insert    Delete   Back
*****************************************************************************************
WSCHEMA                                           12
CLREFERRALS                                       12
CLREFDET                                          12
  • set OuterJoinConversion = true (default!); performance now become very poor:
Select Expression
    -> Filter
        -> Nested Loop Join (outer)
            -> Filter (preliminary)
                -> Sort (record length: 140, key length: 12)
                    -> Filter
                        -> Nested Loop Join (inner)
                            -> Filter
                                -> Table "CLREFDET" as "R" Access By ID
                                    -> Bitmap
                                        -> Index "CLREFDET_REFID" Range Scan (full match)
                            -> Filter
                                -> Table "WSCHEMA" as "W" Access By ID
                                    -> Bitmap
                                        -> Index "WSCHEMA_STRUCT" Range Scan (full match)
                            -> Procedure "GET_USL_STRUCT" as "GS" Scan
            -> Filter
                -> Table "CLREFERRALS" as "R2" Access By ID
                    -> Bitmap
                        -> Index "PK_CLREFERRALS" Unique Scan
12 records fetched
  14744 ms, 182 read(s), 134897 fetch(es)

Table                              Natural     Index    Update    Insert    Delete   Back
*****************************************************************************************
WSCHEMA                                       132696
CLREFERRALS                                       12
CLREFDET                                          12

This is comparison of explained plans before and after slowdown when OuterJoinConversion = true: Image (left part = "good"; right part = "poor")

Regression can be seen also on 5.0.2.1613 and 5.0.3.1649.

PS. Database and query are published with the kind permission of persons who provided them to IBSurgeon.

pavel-zotov avatar Apr 24 '25 20:04 pavel-zotov