#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 и как писать быстрые и оптимальные запросы? Как это понять?
Комментарии:
1. В чем заключается ваш вопрос?
2. Почему запрос с одинаковым пониманием условий работает так по-разному? Как работает оптимизатор FB и как писать быстрые и оптимальные запросы? Как это понять?
3. К сожалению, оптимизатор в Firebird довольно тупой. Основная рекомендация такова: не добавляйте фиктивные условия. Вы смотрели план или объяснили план запроса?
4. Да, простые в последней строке имеют другой порядок:
PLAN JOIN (T2 NATURAL, T1 INDEX (T1_ID_IDX), T3 INDEX (T3_ID_IDX))
vsPLAN 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 уже несколько лет не поддерживается).