powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Оптимизация
4 сообщений из 4, страница 1 из 1
Оптимизация
    #36094118
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оптимизацией в ДБ2 доселе много не занимался, и этот запрос перевернул многое в моём понимании работы баз данных

Есть сравнительно простой запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT dt.DOCUMENT_TASK_ID , ' ' AS NAME ,
	dt.DATETIME_DUE, dt.DATETIME_COMPLETED,	dt.DATETIME_START, dt.DATETIME_EXTENSION, dt.DATETIME_DUE_NEW, 
	dt. DATETIME_LAST_REMINDER, dt.TASK_STATUS_ID ,
	dt.EXEMPT_REMINDER_FL, dt.TASK_ID, dt.ASSIGNMENT_ID, dt.DOCUMENT_ID, dt.runtime_group_id,
	d.config_id, dt. ADDED_BY, dt.MODIFIED_BY, dt.DELETED_BY, d.config_id 
FROM document d ,
	document_task dt ,
	task_status ts 
WHERE d.document_id = dt.document_id 
	AND (dt.datetime_due < CURRENT TIMESTAMP
        OR dt.datetime_due_new < CURRENT TIMESTAMP
        ) 
	AND d.config_id =  122  
	AND dt.task_status_id = ts.task_status_id 
	AND ts.task_status_id IN ( 1  ,  2  ,  3  ,  6  ,  7  ,  8  ,  10  ,  11 ) 
	AND d.datetime_deleted IS NULL 	
    AND ts.datetime_deleted IS NULL 	
    AND dt.datetime_deleted +  0  seconds IS NULL 	
    AND dt.datetime_completed IS NULL
Весь запрос на продакшене выполняется более 8 минут и вытягивает около 200 строк

Всего записей:
document 6335842
document_task 43356203
task_status 7

План выполнения сделан в АкваСтудио и приатачен

Индексы исползуемые при соединении:
Код: plaintext
1.
2.
IDX_DOCTASK11       DOCUMENT_TASK   +TASK_STATUS_ID+DATETIME_DUE+DATETIME_DUE_NEW+DOCUMENT_TASK_ID+DATETIME_DELETED 
IDX_DOC_DT_DELN3    DOCUMENT        +DOCUMENT_ID+DATETIME_DELETED
SQL050121221500870  TASK_STATUS     +TASK_STATUS_ID

Я решил попытаться сделать что-то получше вложенных циклов

Сделал соединение document и document_task без поиска по датам - 72091 строк [Execution: 82156/ms] !!!
Хотя стоимость при этом была за 900 тысяч!!!
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
    select count(*) 
    from document d, document_task dt 
    where 
    d.document_id = dt.document_id     
    AND d.config_id =  122  
    AND d.datetime_deleted IS NULL 
    AND dt.datetime_deleted +  0  seconds IS NULL 
    AND dt.datetime_completed IS NULL
При добавлении условий (dt.datetime_due < CURRENT TIMESTAMP OR dt.datetime_due_new < CURRENT TIMESTAMP) появился хеш-джоин, но стоимость была более 800 тысяч, выполнение продолжалось более 15 минут, после чего я снял

Я создал пару индексов
Код: plaintext
1.
2.
3.
create index idx_ush_document ON document(config_id, DATETIME_DELETED, DOCUMENT_ID)
create index idx_ush_doc_task ON document_task(datetime_deleted, datetime_completed,
 	datetime_due, datetime_due_new, document_id)
но они не подхватываются ни одним из запросов.

Хеш-джоин оказал по стоимости дороже нестед лупсов! Такое вижу впервые.
Запрос с меньшим количеством условий выбирает всего 72к записей за 82 секунды, но потом эти записи фильтруются ещё одним условием и джоинятся к таблице из 7 записей 800 секунд!!
Индексы прямо по условиям не подхватываются!!

Какие будут ещё идеи?
...
Рейтинг: 0 / 0
Оптимизация
    #36094129
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
план выполнения
...
Рейтинг: 0 / 0
Оптимизация
    #36094336
Vladimir Kiselev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mwolf,

Для оптимизации, мы, обычно, сначала используем db2advis, который выдаёт рекомендации по созданию индексов. От этого начинается танец с бубном, особенно если запрос "кружевной".

У меня готовые скриптики есть, может поможет:

Код: plaintext
1.
db2advis -d DBALIAS -a USER/PASSWORD -t  0  -i SCRIPT_IN_FILENAME -o SCRIPT_OUT_FILENAME -m I >LOG_FILENAME
например:
Код: plaintext
db2advis -d alias -a db2admin/password -t  0  -i script.cpl -o script_out.cpl -m I >script.log

В script.cpl надо положить Ваш запрос в чистом виде. Соединение с базой выполнит db2advis сам.

На выходе в script_out.cpl Вы получите что то типа:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
--
--
-- СПИСОК РЕКОМЕНДОВАННЫХ ИНДЕКСОВ
-- ===========================
-- index[1],    3,813MB
   CREATE INDEX "SHL     "."IDX901140917440000" ON "ASN     "."SPARE_LIST"
   ("STATE" ASC) ALLOW REVERSE SCANS ;
   COMMIT WORK ;
   RUNSTATS ON TABLE "ASN     "."SPARE_LIST" FOR INDEX "SHL     "."IDX901140917440000" ;
   COMMIT WORK ;

Это и есть рекомендованные индексы.

А в журнале (в начале файла), Вы увидите что то типа:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
выполнение началось, отметка времени  2009 - 02 - 26 - 13 . 42 . 53 . 198769 
в файле ввода найдено [ 17 ] операторов SQL
Создаются рекомендации индексов...
общее дисковое пространства, нужное для начального набора [  158 , 303 ] Мбайт
максимально доступное общее дисковое пространство     [ 4348 , 698 ] Мбайт
Перебор вариантов набора решений.
Найдено лучшее решение.  Поиск продолжается.
Оптимизация завершена.
   15   индексов в текущем решении
 [ 196457 , 0000 ] единиц времени  (без рекомендаций)
 [ 163227 , 0000 ] единиц времени (с текущим решением)
 [ 16 , 91 %] улучшение
В данном случае 17% улучшения. Понятно, что это теоретически, на практике это не всегда так.

Иногда бывает, что убрав один рекомендованный индекс получаем просто бешенное ускорение. Это и есть процесс оптимизации рекомендаций ;)
Удачи!
...
Рейтинг: 0 / 0
Оптимизация
    #36095971
olzhas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mwolf,

Ну во первых используйте Join, а не знаю как вам а мне кажется ужасно неудобным все условия в одном месте.

Во вторых
Код: plaintext
1.
2.
3.
AND dt.task_status_id = ts.task_status_id 
AND ts.task_status_id IN ( 1  ,  2  ,  3  ,  6  ,  7  ,  8  ,  10  ,  11 ) 
AND ts.datetime_deleted IS NULL 	
Лучше заменить на
Код: plaintext
dt.task_status_id in (select task_status_id from task_status ts where ts.task_status_id IN ( 1  ,  2  ,  3  ,  6  ,  7  ,  8  ,  10  ,  11 ) AND ts.datetime_deleted IS NULL) 	
Так будет более понятно что вы конкретно хотите. Данные таблицы task_status все равно же в результирующий набор не попадают.

в третьих
Код: plaintext
AND dt.datetime_deleted +  0  seconds IS NULL
вот это что такое? я так понял вы к дате прибавляете 0 секунд. Зачем?

в четвертых
что за вложенные циклы? что то я их не вижу.

В пятых
Код: plaintext
SQL050121221500870  TASK_STATUS     +TASK_STATUS_ID
этот индекс уже лишний.

з.ы. Статистику я думаю вы посчитали?
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Оптимизация
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]