Жар-птица и фиктивные условия

#firebird

Вопрос:

У меня есть два похожих вопроса. В одном из случаев есть дополнительный манекен, где условия (1=1, 0=0, истина):

 SELECT t1.*
FROM table1 t1
JOIN table2 t2 ON t2.fk_t1 = t1.id
JOIN table3 t3 ON t3.id = t1.fk_t3
WHERE
    0 = 0 AND /* with this in 1st case, without this line in 2nd case */
    t3.field = 6
    AND EXISTS (SELECT 1 FROM table2 x WHERE x.fk2_t2 = t2.id)
 

Все необходимые поля проиндексированы.

В каждом конкретном случае Firebird (обе версии 2.1 и 3.0) работает по-разному, и статистика чтения выглядит примерно так:

1-й случай (с 0=0):

 Query Time
------------------------------------------------
Prepare       : 32,00 ms
Execute       : 1 046,00 ms
Avg fetch time: 61,53 ms

Operations
------------------------------------------------
Read   : 8 342
Writes : 1
Fetches: 1 316 042
Marks  : 0


Enhanced Info:
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
|          Table Name           |  Records  |  Indexed  | Non-Indexed | Updates | Deletes | Inserts | Backouts |  Purges  | Expunges |
|                               |   Total   |   reads   |    reads    |         |         |         |          |          |          |
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
|TABLE2                         |         0 |      4804 |           0 |       0 |       0 |       0 |        0 |        0 |        0 |
|TABLE1                         |         0 |         0 |       96884 |       0 |       0 |       0 |        0 |        0 |        0 |
|TABLE3                         |         0 |    387553 |           0 |       0 |       0 |       0 |        0 |        0 |        0 |
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
 

И во 2-м случае (без фиктивного условия):

 Query Time
------------------------------------------------
Prepare       : 16,00 ms
Execute       : 515,00 ms
Avg fetch time: 30,29 ms

Operations
------------------------------------------------
Read   : 7 570
Writes : 1
Fetches: 648 103
Marks  : 0


Enhanced Info:
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
|          Table Name           |  Records  |  Indexed  | Non-Indexed | Updates | Deletes | Inserts | Backouts |  Purges  | Expunges |
|                               |   Total   |   reads   |    reads    |         |         |         |          |          |          |
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
|TABLE2                         |         0 |       506 |      152655 |       0 |       0 |       0 |        0 |        0 |        0 |
|TABLE1                         |         0 |       467 |           0 |       0 |       0 |       0 |        0 |        0 |        0 |
|TABLE3                         |         0 |      1885 |           0 |       0 |       0 |       0 |        0 |        0 |        0 |
 ------------------------------- ----------- ----------- ------------- --------- --------- --------- ---------- ---------- ---------- 
 

Запросы имеют разные планы выполнения.

 PLAN JOIN (T2 NATURAL, T1 INDEX (T1_ID_IDX), T3 INDEX (T3_ID_IDX)) 

PLAN JOIN (T1 NATURAL, T3 INDEX (T3_ID_IDX1), T2 INDEX (T2_FK_T1_IDX))
 

Это странно для меня. Почему запрос с одинаковым пониманием условий работает так по-разному? Как работает оптимизатор FB и как писать быстрые и оптимальные запросы? Как это понять?

P.S. https://github.com/FirebirdSQL/firebird/issues/6941

Комментарии:

1. В чем заключается ваш вопрос?

2. Почему запрос с одинаковым пониманием условий работает так по-разному? Как работает оптимизатор FB и как писать быстрые и оптимальные запросы? Как это понять?

3. К сожалению, оптимизатор в Firebird довольно тупой. Основная рекомендация такова: не добавляйте фиктивные условия. Вы смотрели план или объяснили план запроса?

4. Да, простые в последней строке имеют другой порядок: PLAN JOIN (T2 NATURAL, T1 INDEX (T1_ID_IDX), T3 INDEX (T3_ID_IDX)) vs PLAN JOIN (T1 NATURAL, T3 INDEX (T3_ID_IDX1), T2 INDEX (T2_FK_T1_IDX))

5. Я бы рекомендовал создать отчет об ошибке на github.com/FirebirdSQL/firebird/issues для Firebird 3.0 (Firebird 2.1 уже несколько лет не поддерживается).