|
Что касается планирования
|
|||
---|---|---|---|
#18+
Ниже я привожу ситуацию с которой столкнулся и свои по ее поводу рассуждения(наблюдения) (несостоятельные, в виду того, что они ни к чему не привели). Прошу Ваших разъяснений. С уважением, Валентин. Вот такой запрос (предполагается связь BaseLKart->>LKart): SELECT FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') and (T.YEARMONTH<='200101')) and(B.LSCHET=T.LSCHET) IB5 выдает: PLAN JOIN (T INDEX (RDB$FOREIGN55,RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) (*) При этом имеем: - Для LKart INDICES: ... LSCHETYEARMONTH: LSCHET, YEARMONTH; RDB$FOREIGN50: YEARMONTH, KODFLATTYPE; RDB$FOREIGN55: YEARMONTH, KODHOUSE; RDB$PRIMARY49: YEARMONTH, LSCHET; ... - Для BaseLKart INDICES: ... RDB$PRIMARY47: LSCHET; ... Явное указание плана: JOIN (T INDEX (RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) принимается без возражений. Если модифицировать WHERE таким образом: (абсурдность условия не важно) WHERE ((T.YEARMONTH>='200101') and (T.YEARMONTH<='200101')and (T.YEARMONTH='200101')) and(B.LSCHET=T.LSCHET) Получим: PLAN JOIN (T INDEX (RDB$FOREIGN55,RDB$PRIMARY49, RDB$FOREIGN50),B INDEX (RDB$PRIMARY47)) (**) Дальнейшее расширение WHERE подобным образом в PLAN'е ничего не меняет, т.к. исчерпаны индексы, начинающиеся на YEARMONTH В случае: WHERE ((T.YEARMONTH>='200101') >>OR<< (T.YEARMONTH<='200101')) (***) and(B.LSCHET=T.LSCHET) Получаем: PLAN JOIN (B NATURAL,T INDEX (LSCHETYEARMONTH,RDB$PRIMARY49,RDB$FOREIGN50,RDB$FOREIGN55,RDB$PRIMARY49,RDB$FOREIGN50,RDB$FOREIGN55)) При этом, можно предположить, что IB рассуждает так: "Принимая во внимание, что: 1. Условие отбора для LKart 'OR' а, значит, придется отдельно сканировать ее для каждого подусловия; 2. Мне 'по барабану', что данные подусловия по одному и тому же полю и я все равно буду проверять их отдельно при отдельном же проходе, используя отдельные индексы(см. (*) и (**)); Посему проще пройтись по всему BaseLKart, попутно отбирая из LKart". (Хотя, все равно не понятен хвост, причем такой длинный, после LSCHETYEARMONTH. Кстати, если его отбросить в явном указании плана, запрос обрабатывается мгновенно, против почти 10 секунд до начала Fetch, да и сам Fetch проходит урывками, запинаясь секунд на 5 после каждых 975 записей). Впрочем, гипотеза о желании IB избежать лишних проходов не состоятельна в ввиду все тех же (*) и (**). Если к (***) явно указать: PLAN JOIN (T INDEX (RDB$FOREIGN55,RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) IB ругается такими словами: 'index RDB$FOREIGN55 cannot be used in the specified plan' А вот PLAN JOIN (T INDEX (RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) принимает, правда, расширяя его до PLAN JOIN (T INDEX (RDB$PRIMARY49, RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)). В общем, как все это интерпретировать ? ??? Объясните, пожалуйста, значение выражения типа TABLE INDEX(INDEXNAME1[, INDEXNAME2[,...]]). Похоже, я не правильно его понимаю. А понимаю я его так: 'При обработке запроса TABLE сканируется по INDEXNAME1, затем по INDEXNAME2 и т.д. Затем к результату применяется соответствующая логическая операция'. Кроме того, если в программе я явно указываю план обработки запроса, используя имена системных индексов, могу ли я быть уверен, что в будущем, при каких-либо условиях данные имена не поменяются. Естественно, не при сознательном изменении соответствующих индексов - тут все ясно. Не совсем дурак, однако Кроме того, если не указывать явно план, соглашаясь на предложенный при отладке запроса план оптимизатора IB, не может-ли с течением времени (ростом БД) IB поменять данный план. Valk, sod@dn.farlep.net -------------------------------------------------------------------------------------------------- ПРИВОЖУ СТАТИСТИКУ ПО ОБРАБОТКЕ ЗАПРОСОВ: SELECT T.YEARMONTH FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') and (T.YEARMONTH<='200101')) and(B.LSCHET=T.LSCHET) Current memory = 1006592 Delta memory = -25600 Max memory = 1165408 Elapsed time= 5.77 sec Buffers = 256 Reads = 2237 Writes 0 Fetches = 52232 ---------------------------------------------------------- SELECT T.YEARMONTH FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') and (T.YEARMONTH<='200101')and (T.YEARMONTH='200101')) and(B.LSCHET=T.LSCHET) Current memory = 1015808 Delta memory = 6144 Max memory = 1165408 Elapsed time= 5.77 sec Buffers = 256 Reads = 2393 Writes 0 Fetches = 52302 ---------------------------------------------------------- SELECT T.YEARMONTH FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') and (T.YEARMONTH<='200101')) and(B.LSCHET=T.LSCHET) PLAN JOIN (T INDEX (RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) Current memory = 1003520 Delta memory = -3072 Max memory = 1165408 Elapsed time= 5.76 sec Buffers = 256 Reads = 2297 Writes 0 Fetches = 52180 ---------------------------------------------------------- SELECT T.YEARMONTH FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') OR (T.YEARMONTH<='200101')) and(B.LSCHET=T.LSCHET) Current memory = 1032192 Delta memory = -1024 Max memory = 1165408 Elapsed time= 92.88 sec Buffers = 256 Reads = 2280 Writes 0 Fetches = 2440629 --------------------------------------------------------- SELECT T.YEARMONTH FROM lKart T ,BaseLKart B WHERE ((T.YEARMONTH>='200101') or (T.YEARMONTH<='200101')) and(B.LSCHET=T.LSCHET) PLAN JOIN (T INDEX (RDB$PRIMARY49),B INDEX (RDB$PRIMARY47)) Current memory = 1009664 Delta memory = 6144 Max memory = 1165408 Elapsed time= 5.77 sec Buffers = 256 Reads = 2297 Writes 0 Fetches = 52257 --------------------------------------------------------- mailto:sod@dn.farlep.net ... |
|||
:
Нравится:
Не нравится:
|
|||
27.11.2001, 07:51 |
|
|
start [/forum/topic.php?fid=40&fpage=538&tid=1581315]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
37ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
31ms |
get tp. blocked users: |
1ms |
others: | 37ms |
total: | 148ms |
0 / 0 |