Ова страница је машински преведена. Прочитајте енглески оригинал. English

IBSurgeon библиотека

IBAnalyst: Савети и трикови

Овај текст је првобитно написан 2012. године, важи за верзије 1.0 - 2.5, у верзијама 3.0-5.0 било је много промена које нису могле бити одражене. Молимо прочитајте документацију или нас контактирајте за подршку: [email protected].

Нека питања на која није одговорено у IBAnalyst препорукама и/или Помоћи:

1. Како поново изградити индексе на PRIMARY, FOREIGN или UNIQUE ограничењима?

О: За Firebird верзије 1.0-2.5. Да, не можете користити ALTER INDEX xxx INACTIVE/ACTIVE на индексима ограничења. Ако видите дубок или фрагментован индекс на овом ограничењу, можете користити посебан трик (који gbak користи при рестаурацији):

RDB$INDICES има RDB$INDEX_INACTIVE заставицу која је null или 0 ако је индекс активан (након CREATE INDEX или ALTER INDEX ACTIVE). 1 значи да је индекс неактиван (након ALTER INDEX INACTIVE). Али постоји и вредност 3 која се користи за означавање неактивних индекса на ограничењима. Дакле, можете поставити RDB$INDEX_INACTIVE=3 за тај индекс, COMMIT, а затим вратити вредност на 0 и поново комитовати - индекс ће бити поново изграђен.

За Firebird 3.0-5.0 - једноставно урадите ALTER INDEX indexname ACTIVE

2. Користио сам све IBAnalyst препоруке, али ово неће помоћи да се убрзају упити.

О: Ово је посебан проблем где IBAnalyst не може помоћи. Овде могу бити 2 узрока проблема:

  1. Индекси имају застарелу статистику. Можете освежити статистику индекса командом SET STATISTICS INDEX xxx (више детаља на http://www.ibase.ru/proc_selectivity/).

  2. Једноставно не постоји одговарајући индекс за неки услов коришћен у упиту.

  3. Упити су веома сложени, или оптимизатор не може да оптимизује упит, па је неопходно рефакторисати упит.

  4. У неким случајевима видећете “фрагментоване табеле” одмах након рестаурације.

Нормално, Firebird и InterBase (без параметра -use_all_space) резервишу око 25% простора на страницама података за будуће уметање, ажурирање или брисање (да би сместили верзије записа). Али, са било којом величином странице базе (1, 2, 4 или 8 к) видећете ~50% фрагментације за табеле које имају малу величину записа (око ~12-20 бајтова, на пример, табела са 2 целобројна поља има просечну величину записа = 12 бајтова).

Ово је у реду, сматрајте то неким магичним бројем сервера (или понашањем).

Дакле, ако имате такве табеле са малим записима, можете:

а) игнорисати упозорење “фрагментовано” за те табеле

б) смањити “фрагментовано %” на 45%, на пример, у IBAnalyst Options дијалогу.

4. Верзије записа за табелу која не сме бити ажурирана

Ако видите верзије записа на табели која не сме бити ажурирана (на пример, табела са евиденцијом догађаја) - не брините, ове верзије су генерисане брисањем.

Дакле, знаћете колико је тренутних записа у табели и колико је записа обрисано.

Ово важи само ако је MaxVer = 1. Ако је > 1, онда ову табелу ажурира нека апликација. Ако сте заиста сигурни да ова табела никада не сме бити ажурирана, боље је поставити “before update” тригер са изузетком да бисте пронашли која апликација прави ажурирања.

5. BLOB-ови могу изазвати фрагментацију табеле.

Механизам складишти BLOB-ове на 3 различита начина:

  1. Ако садржај BLOB-а стане на страницу података (довољно слободног простора), биће ускладиштен на тој страници података близу свог записа (или верзије).

  2. Ако садржај BLOB-а не стане на страницу података, биће ускладиштен на посебној страници.

  3. Ако у случају 2 BLOB не стане на једну страницу података, креира се страница показивача која показује на одговарајуће BLOB странице.

Случај 1 се дешава у зависности од величине ускладиштеног BLOB-а и величине странице базе. На пример, ако сте имали величину странице 4K и BLOB-ове просечне величине ~5K, они се не чувају на страницама података, већ на додатним BLOB страницама.

Али ако направите резервну копију базе и рестаурирате је са величином странице 8K, BLOB-ови ће стати на страницу података и биће ускладиштени са записима, изазивајући високу фрагментацију записа.

IBAnalyst означава ове табеле као Pale (колона Records) и савет показује процењене записе за ту табелу (на основу броја страница података) и стварну просечну вредност попуњености (%).

Ако ваш упит чита било која поља осим BLOB-ова из те табеле, природно скенирање, спајање или агрегација ће се извршавати веома споро.

Једино решење да се то избегне: креирајте додатну табелу (повезану 1-1 са оригиналном табелом) и преместите све BLOB колоне које имају просечну величину мању од величине странице у њу.

У том случају не покушавајте да направите резервну копију/рестаурацију са већом величином странице! То ће изазвати да BLOB-ови који нису могли стати на странице података са тренутном величином странице, буду постављени на странице података током рестаурације са већом величином странице. Дакле, ваше табеле са BLOB-овима биће више фрагментоване него раније.

Такође се не препоручује рестаурација са мањом величином странице, јер може смањити перформансе за индексе и табеле без BLOB-ова.

Такође не би требало да покушавате да промените BLOB поља у varchar поља - varchar поља су увек ускладиштена као део записа, па запис може имати 2 или више фрагмената (бити постављен на 2 или више страница података) ако не стане на страницу података.

п.с. IBAnalyst може пријавити ове табеле “грешком”, на пример, табела је имала BLOB поља са подацима, али су уклоњена из структуре табеле. Нажалост, не постоји конфигурабилна опција за то упозорење, јер то израчунавамо тачно из података које сервер пријављује (статистика).

6. VerLen и RecLength веза

а) VerLen >= 90% од RecLength: верзије које видите у колони Version су углавном брисања записа. Што је више записа обрисано, RecLength ће бити мањи (до 0 бајтова). Такође VerLen може бити већи од RecLen ако ажурирате табелу са већим string подацима него што је било ускладиштено у оригиналним записима.

б) VerLen <= 80% од RecLength: верзије су углавном ажурирања записа.

Не можемо прецизније разликовати ове случајеве јер статистика показује просечну величину записа и верзије за целу табелу, док видљиви број верзија за конкурентне трансакције може варирати.

7. Зашто IBAnalyst назива неке индексе “лошим”?

Индекси са вредношћу селективности нижом од 0.01 означени су као “лоши” у IBAnalyst-у (погледајте Index view помоћ). Постоји неколико разлога зашто се одређени индекс назива лошим:

  1. Селективност тог индекса је нижа од 0.01. Теоретски, оптимизатор не би требало да користи тај индекс, али га користи ако не постоје други индекси (за where, order by или join клаузулу, барем).

  2. Такав индекс изазива веома споро сакупљање смећа. Овај проблем не постоји у InterBase 7.1/7.5, и биће исправљен у Firebird 2.0.

  3. Овај индекс чини процес рестаурације веома спорим, и креира се веома споро (create/alter index active). То је зато што је ланац бројева записа велики за један кључ индекса.

  4. Ако се овај индекс користи у where клаузули, употреба меморије зависиће од вредности која се претражује (величина битмаске). Пошто ланац записа може бити велики (много дупликата кључева), потрошња меморије ће такође бити велика.

  5. Ако се тај индекс користи у “order by”, и има много дупликата углавном у нижим вредностима кључева (у зависности од реда сортирања индекса), биће много читања страница индекса, што ће успорити упит.

То је зато што IBAnalyst не може игнорисати постојање таквих индекса.

Најгори случај за индекс је када има Uniques колону = 1, тј. све вредности за индексирану колону су исте. Ови индекси су наведени у “Useless indices” на Summary страници.

Наравно, за вашу апликацију такав индекс може бити “добар”. На пример, ако записи имају “archive” заставицу у некој колони, и ваша апликација претражује по индексу на тој колони само за тренутне, неархивиране податке. Дакле, на вама је да одлучите да ли смо у праву што тај индекс називамо “лошим” или не.

8. Шта ако је “лош” индекс креиран од стране FOREIGN KEY ограничења?

Па, претходни параграф показује да је боље уклонити “лоше” индексе (ако их не користите за претрагу кључева који имају мање дупликата од других кључева). Али, ако је такав индекс креиран од стране страног кључа, можете га уклонити само уклањањем страног кључа. Уклањање страног кључа ће онемогућити проверу релационог ограничења, што може бити неприхватљиво.

Можете заменити FK тригерима, али са одређеним ограничењима. FK контролише релације записа користећи индекс, и индекс “види” све кључеве за све записе независно од стања трансакција. Али тригери раде само у контексту трансакције клијента. Дакле, замењујући FK тригерима, морате бити сигурни да:

  • Записи неће бити обрисани из главне табеле, или се бришу у режиму “snapshot table reserving”

  • Колона, коју користи PK у главној табели, никада неће бити измењена. Ово можете ограничити помоћу before update тригера.

Ако ћете одржавати ове услове, можете уклонити одређени страни кључ. Наравно, немојте ручно креирати индекс на тој колони.

9. Зашто у реду процента верзије података постоји само 12 мегабајта података, а ја имам базу од 140 мегабајта?

  1. IBAnalyst овде приказује “чисту” количину података, без бројања других структура базе (индекса, метаподатака…) и фрагментације страница.

  2. Након рестаурације, InterBase и Firebird остављају слободан простор (15-25%) на страницама података како би убрзали будућа ажурирања и брисања.

  3. Постоји специфично понашање сервера када оставља странице података фрагментиране за ~50%, ако је величина записа у тој табели мала, око 11-22 бајта.

10. Како побољшати перформансе оптимизатора у случају честих ажурирања

Статистика индекса се чува у колони RDB$INDICES.RDB$STATISTICS и ажурира се на 3 начина:

  1. SET STATISTICS INDEX

  2. ALTER INDEX ACTIVE, или CREATE INDEX …

  3. процес рестаурације (сви индекси се поново граде, као и “ALTER INDEX ACTIVE”)

Оптимизатор користи ове статистичке информације за припрему упита. Користећи вредности статистике, оптимизатор може одлучити да је индекс “довољно добар” или “није користан” за преузимање записа.

Ако статистика није ажурирана дуже време, оптимизатор може произвести лош план јер постојеће вредности статистике не одговарају стварном стању ствари, јер се подаци у табели могу значајно променити (на пример, број записа је повећан 5-10 пута, или обрнуто, сви записи су обрисани).

Можете заменити лош аутоматски план упита експлицитним PLAN-ом за одређени упит, али то није добар приступ, јер се подаци могу значајно променити након што је план развијен.

Алтернативни (и прави) начин је да периодично освежавате статистику применом SET STATISTICS изјаве за све индексе. Можете заказати покретање SQL скрипте за освежавање статистике користећи ISQL или готови алат gidx (само за Windows).

Ако имате неке табеле са периодично поново учитаним различитим записима, овај приступ неће помоћи. Размотримо пример:

  • Табела A се пуни подацима 4-5 пута дневно.
  • Након обраде учитаних података, сви записи у табели A се бришу.

У овом случају можемо видети 2 исправне вредности статистике за индексе на табели A - када је напуњена подацима и када је празна. Дакле, статистика поново израчуната на напуњеној табели биће бескорисна када је табела празна, и обрнуто.

Да бисте то избегли, потребно је поново израчунати статистику за индексе на табели A само када је табела напуњена подацима. Најбоље је пре него што се покрену упити на тој табели.

Од верзије 1.91, IBAnalyst приказује разлику у статистици индекса и омогућава вам да је поново израчунате у било ком тренутку. Прво треба да погледате информације о записима у табели - да ли је то уобичајен просечан број записа или није. Ако јесте, можете сигурно поново израчунати селективност индекса. Ако није - можда је боље не дирати статистику индекса, јер то може довести до тога да оптимизатор произведе још горе планове упита.