{"id":9258,"date":"2026-01-08T12:10:39","date_gmt":"2026-01-08T11:10:39","guid":{"rendered":"https:\/\/pomoc.comarch.pl\/cee\/?post_type=ht_kb&#038;p=9258"},"modified":"2026-01-08T12:10:40","modified_gmt":"2026-01-08T11:10:40","slug":"optymalizacja-wydajnosci","status":"publish","type":"ht_kb","link":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/","title":{"rendered":"Optymalizacja wydajno\u015bci"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 ez-toc-wrap-left counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Spis tre\u015bci<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Prze\u0142\u0105cznik Spisu Tre\u015bci\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Grupa_docelowa\" >Grupa docelowa<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Definicje_terminow\" >Definicje termin\u00f3w<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Podstawy\" >Podstawy<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wytyczne\" >Wytyczne<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Cele_optymalizacji\" >Cele optymalizacji<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Najpierw_pomiar_i_weryfikacja_a_pozniej_zmiana\" >Najpierw pomiar i weryfikacja, a p\u00f3\u017aniej zmiana<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Weryfikacja_dostepu_do_bazy_danych\" >Weryfikacja dost\u0119pu do bazy danych<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Zuzycie_pamieci\" >Zu\u017cycie pami\u0119ci<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Pomiary_wydajnosci\" >Pomiary wydajno\u015bci<\/a><ul class='ez-toc-list-level-6' ><li class='ez-toc-heading-level-6'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Monitory_wydajnosci\" >Monitory wydajno\u015bci<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-6'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Protokoly_profilowania\" >Protoko\u0142y profilowania<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-6'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Profilery_pamieci\" >Profilery pami\u0119ci<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-6'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Profilery_CPU\" >Profilery CPU<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-6'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wyprowadzanie_zapytan_bazodanowych\" >Wyprowadzanie zapyta\u0144 bazodanowych<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Indeksy\" >Indeksy<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Odczyt_z_wykorzystaniem_indeksu\" >Odczyt z wykorzystaniem indeksu<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wybor_atrybutow_indeksu\" >Wyb\u00f3r atrybut\u00f3w indeksu<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Zapis_z_wykorzystaniem_indeksu\" >Zapis z wykorzystaniem indeksu<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Relacje\" >Relacje<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Dane_ruchowe\" >Dane ruchowe<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Dane_podstawowe\" >Dane podstawowe<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#ORDER_BY\" >ORDER BY<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#GROUP_BY\" >GROUP BY<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#DISTINCT\" >DISTINCT<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Optymalizacje\" >Optymalizacje<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Dostep_do_bazy_danych\" >Dost\u0119p do bazy danych<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Znaczenie_wspoldzielonego_cache\" >Znaczenie wsp\u00f3\u0142dzielonego cache<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_getObjectArray\" >Wykorzystanie getObjectArray<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_INSERT\" >Wykorzystanie INSERT<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Stale_w_OQL\" >Sta\u0142e w OQL<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_getObjectIterator\" >Wykorzystanie getObjectIterator<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_getResultSet\" >Wykorzystanie getResultSet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_getUpdateStatement\" >Wykorzystanie getUpdateStatement()<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-34\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Przetwarzanie_blokowe_w_klasach_logiki\" >Przetwarzanie blokowe w klasach logiki<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-35\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wyszukiwanie_instrukcji_bazodanowych_w_aplikacjach\" >Wyszukiwanie instrukcji bazodanowych w aplikacjach<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-36\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wyszukiwania_i_listy\" >Wyszukiwania i listy<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-37\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wybor_wartosci_domyslnych_dla_pol_wyszukiwania\" >Wyb\u00f3r warto\u015bci domy\u015blnych dla p\u00f3l wyszukiwania<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-38\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Dostosowanie_specyficzne_dla_klienta\" >Dostosowanie specyficzne dla klienta<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-39\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Wykorzystanie_fragmentow\" >Wykorzystanie fragment\u00f3w<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-40\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/optymalizacja-wydajnosci\/#Aplikacje_interaktywne\" >Aplikacje interaktywne<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<p data-start=\"34\" data-end=\"271\">W ramach rozwoju lub adaptacji mo\u017ce zaistnie\u0107 potrzeba poprawy czasu wykonywania programu aplikacyjnego. Niniejszy artyku\u0142 opisuje w szczeg\u00f3lno\u015bci mo\u017cliwo\u015bci optymalizacji w programach aplikacyjnych przy dost\u0119pie do us\u0142ugi persystencji.<\/p>\n<h3 data-start=\"34\" data-end=\"271\" id=\"grupa-docelowa\" ><span class=\"ez-toc-section\" id=\"Grupa_docelowa\"><\/span>Grupa docelowa<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p data-start=\"294\" data-end=\"356\">Grup\u0105 docelow\u0105 niniejszego artyku\u0142u s\u0105 deweloperzy aplikacji.<\/p>\n<h3 data-start=\"294\" data-end=\"356\" id=\"definicje-terminow\" ><span class=\"ez-toc-section\" id=\"Definicje_terminow\"><\/span>Definicje termin\u00f3w<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><strong>Notacja O<\/strong> &#8212; aby poprawi\u0107 wydajno\u015b\u0107 systemu, konieczna jest wiedza, ile czasu zajmuj\u0105 poszczeg\u00f3lne operacje. Czas wykonania operacji jest jednak cz\u0119sto zale\u017cny od zakresu przetwarzanych danych. Z tego powodu stosuje si\u0119 notacj\u0119 O w celu oszacowania z\u0142o\u017cono\u015bci operacji. Pe\u0142n\u0105, matematycznie poprawn\u0105 definicj\u0119 mo\u017cna znale\u017a\u0107 w odpowiedniej literaturze podstawowej.<\/li>\n<\/ul>\n<p>Zbi\u00f3r <em>O(f(n))<\/em> obejmuje wszystkie funkcje<em> g(n)<\/em>, dla kt\u00f3rych istniej\u0105 sta\u0142e <em>c<\/em> oraz <em>n\u2080<\/em> takie, \u017ce dla wszystkich <em>m &gt; n\u2080<\/em> zachodzi:<\/p>\n<p data-start=\"748\" data-end=\"896\"><em>0 \u2264 g(m) &lt; c \u00b7 f(m)<\/em>.<\/p>\n<p data-start=\"898\" data-end=\"949\">W praktyce stosowane s\u0105 g\u0142\u00f3wnie nast\u0119puj\u0105ce zbiory:<\/p>\n<ul>\n<li data-start=\"952\" data-end=\"991\"><em>O(c)<\/em> dla wszystkich funkcji sta\u0142ych<\/li>\n<li data-start=\"994\" data-end=\"1005\"><em>O(log(n))<\/em><\/li>\n<li data-start=\"1008\" data-end=\"1014\"><em>O(n)<\/em><\/li>\n<li data-start=\"1017\" data-end=\"1030\"><em>O(n \u00b7 log(n))<\/em><\/li>\n<\/ul>\n<p data-start=\"1053\" data-end=\"1089\">Przyjmuje si\u0119 nast\u0119puj\u0105ce za\u0142o\u017cenia:<\/p>\n<ol>\n<li data-start=\"1094\" data-end=\"1349\">Dost\u0119p do tablicy haszuj\u0105cej ma sta\u0142y koszt czasowy, czyli nale\u017cy do <em>O(c)<\/em>. Chocia\u017c w og\u00f3lnym przypadku koszt wynosi <em>O(n)<\/em>, to przy za\u0142o\u017ceniu dobrej funkcji haszuj\u0105cej oraz ograniczeniu stopnia wype\u0142nienia tabeli do 75% takie oszacowanie jest uzasadnione.<\/li>\n<li data-start=\"1353\" data-end=\"1418\">Dost\u0119p do indeksu bazy danych ma koszt czasowy rz\u0119du <em>O(log(n))<\/em>.<\/li>\n<li data-start=\"1422\" data-end=\"1484\">Odczyt wszystkich rekord\u00f3w tabeli ma koszt czasowy rz\u0119du<em> O(n)<\/em>.<\/li>\n<\/ol>\n<h3 id=\"podstawy\" ><span class=\"ez-toc-section\" id=\"Podstawy\"><\/span>Podstawy<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p data-start=\"1486\" data-end=\"1666\">Je\u017celi program lub funkcja programu wymaga wi\u0119cej czasu, ni\u017c jest to akceptowalne, problem ten musi zosta\u0107 rozwi\u0105zany. W pierwszej kolejno\u015bci nale\u017cy sprawdzi\u0107 konfiguracj\u0119 systemu:<\/p>\n<ul>\n<li data-start=\"1669\" data-end=\"1786\">sprawdzenie, czy baza danych oraz serwer aplikacyjny dysponuj\u0105 wystarczaj\u0105c\u0105 ilo\u015bci\u0105 fizycznej pami\u0119ci operacyjnej,<\/li>\n<li data-start=\"1789\" data-end=\"1883\">sprawdzenie, czy bufory (cache) bazy danych i serwera aplikacyjnego maj\u0105 odpowiedni rozmiar,<\/li>\n<li data-start=\"1886\" data-end=\"1945\">sprawdzenie, czy wykorzystywany sprz\u0119t spe\u0142nia wymagania,<\/li>\n<li data-start=\"1948\" data-end=\"1952\">itd.<\/li>\n<\/ul>\n<p data-start=\"1954\" data-end=\"2107\">Je\u017celi wszystkie mo\u017cliwo\u015bci przyspieszenia systemu poprzez zmiany konfiguracji zosta\u0142y wyczerpane, przyczyna problemu mo\u017ce le\u017ce\u0107 w u\u017cywanych aplikacjach.<\/p>\n<p data-start=\"2109\" data-end=\"2314\">W dalszej cz\u0119\u015bci podawane warto\u015bci czas\u00f3w i rozmiar\u00f3w s\u0142u\u017c\u0105 wy\u0142\u0105cznie zobrazowaniu zale\u017cno\u015bci i nie odnosz\u0105 si\u0119 bezpo\u015brednio do rzeczywistego systemu. Dodatkowo, nale\u017cy zapozna\u0107 si\u0119 z artyku\u0142em <em>Lista kontrolna systemu<\/em>.<\/p>\n<h4 data-start=\"2109\" data-end=\"2314\" id=\"wytyczne\" ><span class=\"ez-toc-section\" id=\"Wytyczne\"><\/span>Wytyczne<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"2339\" data-end=\"2672\">Aplikacje w Comarch ERP Enterprise musz\u0105 by\u0107 przystosowane do przetwarzania du\u017cych wolumen\u00f3w danych oraz charakteryzowa\u0107 si\u0119 wysok\u0105 wydajno\u015bci\u0105. Oznacza to, \u017ce program musi by\u0107 w stanie przetwarza\u0107 du\u017ce ilo\u015bci danych w czasie akceptowalnym dla u\u017cytkownika, bez nadmiernego zu\u017cycia pami\u0119ci operacyjnej lub innych kluczowych zasob\u00f3w.<\/p>\n<p data-start=\"2674\" data-end=\"3034\">Podstawowe zasady, kt\u00f3re nale\u017cy uwzgl\u0119dnia\u0107 przy tworzeniu wydajnych program\u00f3w, zosta\u0142y opisane poni\u017cej. Bardziej z\u0142o\u017conych zagadnie\u0144 nie da si\u0119 jednak uj\u0105\u0107 w postaci prostych regu\u0142. Z tego powodu po zako\u0144czeniu implementacji programu konieczne jest zmierzenie jego zapotrzebowania na zasoby. W razie potrzeby nale\u017cy nast\u0119pnie skorygowa\u0107 s\u0142abe punkty programu.<\/p>\n<h5 data-start=\"2674\" data-end=\"3034\" id=\"cele-optymalizacji\" ><span class=\"ez-toc-section\" id=\"Cele_optymalizacji\"><\/span>Cele optymalizacji<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"3071\" data-end=\"3380\">Wszystkie serwery aplikacji Comarch ERP Enterprise (SAS) korzystaj\u0105 ze wsp\u00f3lnego systemu bazodanowego (DBS). DBS ma ograniczon\u0105 maksymaln\u0105 wydajno\u015b\u0107. Je\u017celi DBS wykonuje jedno lub kilka z\u0142o\u017conych zapyta\u0144, to r\u00f3wnie\u017c wykonywanie prostych zapyta\u0144 trwa znacznie d\u0142u\u017cej ni\u017c w przypadku nieobci\u0105\u017conego systemu.<\/p>\n<p data-start=\"3071\" data-end=\"3380\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u017celi zapytanie wymaga 10 ms czasu CPU, to przy 0% obci\u0105\u017cenia CPU w DBS jego wykonanie trwa 10 ms. Przy 90% obci\u0105\u017cenia CPU w DBS to samo zapytanie trwa oko\u0142o 100 ms.<\/div><\/section><\/p>\n<p data-start=\"3565\" data-end=\"3790\">Jednym z cel\u00f3w optymalizacji wydajno\u015bci jest to, aby z\u0142o\u017cone zapytania bazodanowe o czasie wykonania powy\u017cej 2\u20133 sekund w normalnej eksploatacji Comarch ERP Enterprise nie wyst\u0119powa\u0142y lub pojawia\u0142y si\u0119 jedynie sporadycznie.<\/p>\n<p data-start=\"3792\" data-end=\"4026\">Podobnie jak z\u0142o\u017cone zapytania, r\u00f3wnie\u017c proste zapytania bazodanowe mog\u0105 prowadzi\u0107 do problem\u00f3w, je\u017celi s\u0105 wykonywane zbyt cz\u0119sto. Wielokrotne wykonywanie prostego zapytania ma taki sam efekt jak wykonanie jednego z\u0142o\u017conego zapytania.<\/p>\n<p data-start=\"3792\" data-end=\"4026\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u017celi zapytanie bazodanowe wymagaj\u0105ce 10 ms czasu CPU jest wykonywane 90 razy na sekund\u0119, to DBS osi\u0105ga 90% obci\u0105\u017cenia CPU.<\/div><\/section><\/p>\n<p data-start=\"4169\" data-end=\"4258\">Kolejnym celem jest zatem ograniczenie liczby wykonywanych prostych zapyta\u0144 bazodanowych.<\/p>\n<p data-start=\"4260\" data-end=\"4826\">Je\u017celi DBS jest przeci\u0105\u017cony, wszystkie operacje w ca\u0142ym systemie Comarch ERP Enterprise ulegaj\u0105 spowolnieniu. Oznacza to, \u017ce przy obci\u0105\u017conym DBS r\u00f3wnie\u017c operacje, kt\u00f3re same w sobie s\u0105 wystarczaj\u0105co szybkie, staj\u0105 si\u0119 dla u\u017cytkownik\u00f3w nieakceptowalnie wolne. W konsekwencji operacja, kt\u00f3ra jest postrzegana jako wolna, nie zawsze jest rzeczywist\u0105 przyczyn\u0105 problem\u00f3w wydajno\u015bciowych. W szczeg\u00f3lno\u015bci, je\u017celi obserwowane jest silnie zmienne zachowanie systemu (raz szybkie, raz wolne), mo\u017cna przypuszcza\u0107, \u017ce przyczyna nie le\u017cy w bezpo\u015brednio obserwowanej operacji.<\/p>\n<p data-start=\"4260\" data-end=\"4826\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">U jednego z klient\u00f3w przej\u0119cie pozycji zam\u00f3wienia trwa 0,5 s. Drukowanie dokumentu dostawy generuje 60 sekund obci\u0105\u017cenia bazy danych. Podczas drukowania dokumentu dostawy przej\u0119cie pozycji zam\u00f3wienia trwa 5 sekund. U\u017cytkownicy skar\u017c\u0105 si\u0119 na s\u0142ab\u0105 wydajno\u015b\u0107 podczas wprowadzania pozycji zam\u00f3wie\u0144, poniewa\u017c jest to kluczowa czynno\u015b\u0107 dla wi\u0119kszo\u015bci z nich.<\/div><\/section><\/p>\n<p data-start=\"5198\" data-end=\"5453\">Podobnie jak obci\u0105\u017cenie DBS spowalnia ca\u0142y system, tak samo obci\u0105\u017cenie CPU na jednym SAS spowalnia wszystkich u\u017cytkownik\u00f3w zalogowanych do tego serwera. Z tego powodu obliczenia intensywnie wykorzystuj\u0105ce CPU powinny by\u0107 unikane w aplikacjach dialogowych.<\/p>\n<p data-start=\"5455\" data-end=\"5581\">Pami\u0119\u0107 operacyjna w ka\u017cdym SAS jest ograniczona, dlatego aplikacja dialogowa mo\u017ce wykorzystywa\u0107 jedynie ograniczon\u0105 jej ilo\u015b\u0107.<\/p>\n<p data-start=\"5583\" data-end=\"5903\">Systemy operacyjne oraz systemy zarz\u0105dzania bazami danych reaguj\u0105 na obci\u0105\u017cenie w bardzo r\u00f3\u017cny spos\u00f3b. Niekt\u00f3re systemy lepiej radz\u0105 sobie z okresami wysokiego obci\u0105\u017cenia ni\u017c inne. W zwi\u0105zku z tym nie mo\u017cna formu\u0142owa\u0107 og\u00f3lnych, uniwersalnych stwierdze\u0144 dotycz\u0105cych wp\u0142ywu wysokiego obci\u0105\u017cenia na czas odpowiedzi systemu.<\/p>\n<h5 data-start=\"5583\" data-end=\"5903\" id=\"najpierw-pomiar-i-weryfikacja-a-pozniej-zmiana\" ><span class=\"ez-toc-section\" id=\"Najpierw_pomiar_i_weryfikacja_a_pozniej_zmiana\"><\/span>Najpierw pomiar i weryfikacja, a p\u00f3\u017aniej zmiana<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"34\" data-end=\"358\">Aby poprawi\u0107 wydajno\u015b\u0107 programu, kt\u00f3rego rozw\u00f3j przebiega\u0142 zgodnie z podstawowymi zasadami, zasadniczo nale\u017cy najpierw przeprowadzi\u0107 pomiary, a dopiero potem wprowadza\u0107 zmiany w programie. Dop\u00f3ki nie jest wiadomo, gdzie zu\u017cywana jest zas\u00f3b krytyczny (pami\u0119\u0107 operacyjna lub czas wykonania), optymalizacja nie ma uzasadnienia.<\/p>\n<p data-start=\"34\" data-end=\"358\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Funkcja <em data-start=\"384\" data-end=\"387\">f<\/em> dzieli si\u0119 na nast\u0119puj\u0105ce cz\u0119\u015bci:<\/p>\n<ol>\n<li data-start=\"425\" data-end=\"487\">gromadzenie danych, kt\u00f3re wymaga 60% ca\u0142kowitego czasu wykonania,<\/li>\n<li data-start=\"491\" data-end=\"551\">obliczanie danych, kt\u00f3re wymaga 5% ca\u0142kowitego czasu wykonania,<\/li>\n<li data-start=\"555\" data-end=\"617\">zapisywanie danych, kt\u00f3re wymaga 20% ca\u0142kowitego czasu wykonania,<\/li>\n<li data-start=\"621\" data-end=\"682\">wy\u015bwietlanie danych, kt\u00f3re wymaga 15% ca\u0142kowitego czasu wykonania.<\/li>\n<\/ol>\n<p data-start=\"684\" data-end=\"782\">Optymalizacja polegaj\u0105ca na skr\u00f3ceniu czasu dzia\u0142ania danej cz\u0119\u015bci o po\u0142ow\u0119 ma nast\u0119puj\u0105ce efekty:<\/p>\n<ol>\n<li data-start=\"786\" data-end=\"888\">skr\u00f3cenie czasu gromadzenia danych o po\u0142ow\u0119 powoduje zmniejszenie ca\u0142kowitego czasu wykonania o 30%,<\/li>\n<li data-start=\"892\" data-end=\"994\">skr\u00f3cenie czasu obliczania danych o po\u0142ow\u0119 powoduje zmniejszenie ca\u0142kowitego czasu wykonania o 2,5%,<\/li>\n<li data-start=\"998\" data-end=\"1100\">skr\u00f3cenie czasu zapisywania danych o po\u0142ow\u0119 powoduje zmniejszenie ca\u0142kowitego czasu wykonania o 10%,<\/li>\n<li data-start=\"1104\" data-end=\"1206\">skr\u00f3cenie czasu wy\u015bwietlania danych o po\u0142ow\u0119 powoduje zmniejszenie ca\u0142kowitego czasu wykonania o 7,5%.<\/li>\n<\/ol>\n<p data-start=\"1208\" data-end=\"1472\">Z powy\u017cszego przyk\u0142adu wynika, \u017ce je\u017celi ca\u0142kowity czas wykonania funkcji <em data-start=\"1282\" data-end=\"1285\">f<\/em> jest zbyt d\u0142ugi, najwi\u0119kszy efekt przynosi optymalizacja cz\u0119\u015bci gromadzenie danych. Natomiast optymalizacja cz\u0119\u015bci obliczanie danych b\u0119dzie dla u\u017cytkownika praktycznie niezauwa\u017calna.<\/p>\n<p data-start=\"1474\" data-end=\"1795\">Przyk\u0142ad ten pokazuje, jak istotne jest najpierw zidentyfikowanie tej cz\u0119\u015bci programu, kt\u00f3ra generuje najwi\u0119ksze zu\u017cycie zasob\u00f3w. Od tego elementu nale\u017cy rozpocz\u0105\u0107 optymalizacj\u0119. Im dok\u0142adniej zostanie zaw\u0119\u017cona funkcja o najwy\u017cszym zapotrzebowaniu na zasoby, tym bardziej ukierunkowana i skuteczna mo\u017ce by\u0107 optymalizacja.<\/div><\/section><\/p>\n<h5 data-start=\"1474\" data-end=\"1795\" id=\"weryfikacja-dostepu-do-bazy-danych\" ><span class=\"ez-toc-section\" id=\"Weryfikacja_dostepu_do_bazy_danych\"><\/span>Weryfikacja dost\u0119pu do bazy danych<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"1848\" data-end=\"2094\">W przypadku z\u0142o\u017conych program\u00f3w do przeprowadzenia miarodajnych pomiar\u00f3w konieczne s\u0105 reprezentatywne dane testowe. Oznacza to, \u017ce dane testowe musz\u0105 pod wzgl\u0119dem zakresu i struktury odpowiada\u0107 przypadkowi u\u017cycia, kt\u00f3ry ma zosta\u0107 zoptymalizowany.<\/p>\n<p data-start=\"2096\" data-end=\"2572\">Tworzenie danych testowych mo\u017ce by\u0107 stosunkowo pracoch\u0142onne. Je\u017celi jest to mo\u017cliwe, zaleca si\u0119 korzystanie z danych rzeczywistych. W przypadku wyst\u0119powania problemu wydajno\u015bciowego u klienta do systemu deweloperskiego partnera powinna zosta\u0107, o ile to mo\u017cliwe, do\u0142\u0105czona kopia bazy danych OLTP zawieraj\u0105ca rzeczywiste dane. Zbyt ma\u0142e lub zbyt prosto ustrukturyzowane dane testowe zniekszta\u0142caj\u0105 wyniki pomiar\u00f3w i mog\u0105 prowadzi\u0107 do optymalizacji niew\u0142a\u015bciwych cz\u0119\u015bci programu.<\/p>\n<p data-start=\"2574\" data-end=\"3486\">Podczas wykonywania pomiar\u00f3w w systemie deweloperskim nale\u017cy pami\u0119ta\u0107, \u017ce baza danych OLTP w tym systemie zazwyczaj nie ma takiego rozmiaru jak baza OLTP w systemie produkcyjnym. W zwi\u0105zku z tym zapytania bazodanowe mog\u0105 wykazywa\u0107 inne czasy wykonania ni\u017c w \u015brodowisku produkcyjnym. Ponadto obci\u0105\u017cenie bazy danych i serwer\u00f3w aplikacyjnych w systemie deweloperskim jest znacznie mniejsze ni\u017c w systemie produkcyjnym. W \u015brodowisku deweloperskim jednocze\u015bnie pracuje zwykle niewielu deweloper\u00f3w, natomiast w systemie produkcyjnym wielu u\u017cytkownik\u00f3w wykonuje r\u00f3wnolegle r\u00f3\u017cne operacje. W efekcie bufory (cache) serwera aplikacyjnego i bazy danych w systemie deweloperskim s\u0105 niemal wy\u0142\u0105cznie dost\u0119pne dla jednej operacji, podczas gdy w systemie produkcyjnym musz\u0105 by\u0107 wsp\u00f3\u0142dzielone przez wiele aktywnych sesji. Z tego powodu pomiary czasu wykonane w systemie deweloperskim nale\u017cy zawsze interpretowa\u0107 z ostro\u017cno\u015bci\u0105.<\/p>\n<p data-start=\"3488\" data-end=\"3969\">Systemy zarz\u0105dzania bazami danych (DBMS) tworz\u0105 dla ka\u017cdego polecenia SQL plan dost\u0119pu. Plan dost\u0119pu opisuje spos\u00f3b, w jaki DBMS uzyskuje dost\u0119p do tabel i indeks\u00f3w podczas wykonywania polecenia SQL. Wszystkie DBMS udost\u0119pniaj\u0105 mo\u017cliwo\u015b\u0107 graficznego wy\u015bwietlenia planu dost\u0119pu. W szczeg\u00f3lno\u015bci w przypadku polece\u0144 SQL o d\u0142ugim czasie wykonania konieczna jest analiza planu dost\u0119pu. W tym celu nale\u017cy korzysta\u0107 z dokumentacji danego DBMS, aby pobiera\u0107 i interpretowa\u0107 plany dost\u0119pu.<\/p>\n<p data-start=\"3971\" data-end=\"4412\">Optymalizator DBMS dzia\u0142a zazwyczaj w oparciu o koszty. Oznacza to, \u017ce na podstawie informacji statystycznych pr\u00f3buje on oszacowa\u0107 koszt wykonania polecenia SQL. Je\u017celi dost\u0119pnych jest kilka alternatywnych plan\u00f3w dost\u0119pu, wybierany jest plan o najni\u017cszym koszcie. Mo\u017ce si\u0119 zatem zdarzy\u0107, \u017ce mimo istnienia odpowiednich indeks\u00f3w nie zostan\u0105 one u\u017cyte, poniewa\u017c koszt dost\u0119pu z wykorzystaniem indeksu jest wy\u017cszy ni\u017c koszt dost\u0119pu bez indeksu.<\/p>\n<p data-start=\"4414\" data-end=\"4846\">Niemal ka\u017cdy DBMS oferuje funkcj\u0119 monitorowania, kt\u00f3ra umo\u017cliwia rejestrowanie zu\u017cycia zasob\u00f3w przez polecenia SQL wykonywane w okre\u015blonym przedziale czasu. Funkcja ta powinna by\u0107 wykorzystywana podczas test\u00f3w obci\u0105\u017ceniowych. W przypadku problem\u00f3w wydajno\u015bciowych w systemie produkcyjnym r\u00f3wnie\u017c mo\u017cna z niej korzysta\u0107, przy czym nale\u017cy bezwzgl\u0119dnie upewni\u0107 si\u0119, \u017ce pomiary nie powoduj\u0105 nadmiernego obci\u0105\u017cenia systemu produkcyjnego.<\/p>\n<p data-start=\"4848\" data-end=\"5140\">Comarch ERP Enterprise mo\u017ce za pomoc\u0105 monitor\u00f3w wydajno\u015bci rejestrowa\u0107 szczeg\u00f3\u0142owe informacje wydajno\u015bciowe dotycz\u0105ce aplikacji i raport\u00f3w. Informacje te mog\u0105 obejmowa\u0107 statystyki dotycz\u0105ce dost\u0119pu aplikacji lub raportu do bazy danych. Dane te nale\u017cy wykorzystywa\u0107 w procesie optymalizacji.<\/p>\n<p data-start=\"5142\" data-end=\"5321\">Protoko\u0142y profilowania dostarczaj\u0105 szczeg\u00f3\u0142owej analizy pojedynczych aplikacji lub akcji zwi\u0105zanych z aplikacjami. Dalsze informacje znajduj\u0105 si\u0119 w rozdziale <em data-start=\"5300\" data-end=\"5320\">Pomiary wydajno\u015bci<\/em>.<\/p>\n<h5 data-start=\"5142\" data-end=\"5321\" id=\"zuzycie-pamieci\" ><span class=\"ez-toc-section\" id=\"Zuzycie_pamieci\"><\/span>Zu\u017cycie pami\u0119ci<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"5355\" data-end=\"5718\">Java wykorzystuje dynamiczne zarz\u0105dzanie pami\u0119ci\u0105 z mechanizmem <em data-start=\"5419\" data-end=\"5438\">garbage collector<\/em>, kt\u00f3ry w tle regularnie usuwa obiekty, do kt\u00f3rych nie istniej\u0105 ju\u017c referencje. Mechanizm ten mo\u017ce prowadzi\u0107 do znacznego obci\u0105\u017cenia CPU, je\u017celi w kr\u00f3tkim czasie tworzona jest bardzo du\u017ca liczba obiekt\u00f3w. Z tego wzgl\u0119du nale\u017cy unika\u0107 niepotrzebnego tworzenia nowych obiekt\u00f3w Java.<\/p>\n<p data-start=\"5720\" data-end=\"5910\">Za pomoc\u0105 profiler\u00f3w pami\u0119ci, takich jak np. <em data-start=\"5765\" data-end=\"5778\">Optimize-It<\/em>, mo\u017cliwa jest analiza liczby tworzonych obiekt\u00f3w poszczeg\u00f3lnych klas. Narz\u0119dzia te nale\u017cy wykorzystywa\u0107 do optymalizacji aplikacji.<\/p>\n<p data-start=\"5912\" data-end=\"6100\">Na ten temat istnieje wiele opracowa\u0144 dost\u0119pnych w Internecie oraz w literaturze specjalistycznej. Z tego powodu zagadnienia zwi\u0105zane z optymalizacj\u0105 zu\u017cycia pami\u0119ci nie s\u0105 dalej omawiane.<\/p>\n<p data-start=\"6102\" data-end=\"6393\">Nale\u017cy zwr\u00f3ci\u0107 uwag\u0119, \u017ce wi\u0119kszo\u015b\u0107 problem\u00f3w wydajno\u015bciowych w aplikacjach biznesowych jest spowodowana niekorzystnym lub zbyt cz\u0119stym dost\u0119pem do bazy danych. Problemy wynikaj\u0105ce z nadmiernego zu\u017cycia pami\u0119ci lub zbyt du\u017cej liczby tymczasowo tworzonych obiekt\u00f3w wyst\u0119puj\u0105 stosunkowo rzadko.<\/p>\n<h5 data-start=\"6102\" data-end=\"6393\" id=\"pomiary-wydajnosci\" ><span class=\"ez-toc-section\" id=\"Pomiary_wydajnosci\"><\/span>Pomiary wydajno\u015bci<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"34\" data-end=\"410\">Do pomiar\u00f3w wydajno\u015bci dost\u0119pne s\u0105 mi\u0119dzy innymi narz\u0119dzia przedstawione w niniejszym rozdziale. Wynikiem pomiaru wydajno\u015bci mo\u017ce by\u0107 zestaw instrukcji bazodanowych, kt\u00f3re odpowiadaj\u0105 za czas odpowiedzi aplikacji lub raportu. W rozdziale <em data-start=\"272\" data-end=\"323\">Wyszukiwanie instrukcji bazodanowych w aplikacjach<\/em> opisano, w jaki spos\u00f3b lokalizowa\u0107 problematyczne instrukcje bazodanowe w aplikacjach.<\/p>\n<h6 data-start=\"34\" data-end=\"410\" id=\"monitory-wydajnosci\" ><span class=\"ez-toc-section\" id=\"Monitory_wydajnosci\"><\/span>Monitory wydajno\u015bci<span class=\"ez-toc-section-end\"><\/span><\/h6>\n<p data-start=\"441\" data-end=\"716\">Monitory wydajno\u015bci w Comarch ERP Enterprise rejestruj\u0105 wybrane operacje przez d\u0142u\u017cszy czas. Rejestrowanie mo\u017cna \u2013 w zale\u017cno\u015bci od poziomu szczeg\u00f3\u0142owo\u015bci \u2013 w\u0142\u0105czy\u0107 r\u00f3wnie\u017c w systemach produkcyjnych. W ramach monitor\u00f3w wydajno\u015bci mierzony jest tak\u017ce czas wykonania poszczeg\u00f3lnych operacji.<\/p>\n<p data-start=\"718\" data-end=\"937\">Za pomoc\u0105 monitor\u00f3w wydajno\u015bci bazy danych ka\u017cdy deweloper aplikacji mo\u017ce kontrolowa\u0107 operacje opracowane przez siebie pod k\u0105tem dost\u0119pu do us\u0142ugi persystencji. W wielu przypadkach sprawdza si\u0119 nast\u0119puj\u0105ce post\u0119powanie:<\/p>\n<ol>\n<li data-start=\"942\" data-end=\"989\">Uruchomienie aplikacji <em data-start=\"965\" data-end=\"986\">Monitory wydajno\u015bci.<\/em><\/li>\n<li data-start=\"993\" data-end=\"1033\">Utworzenie nowego monitora wydajno\u015bci.<\/li>\n<li data-start=\"1037\" data-end=\"1096\">U\u017cycie pliku szablonu <em data-start=\"1059\" data-end=\"1093\">DatabaseMonitor-FullAnalysis.xml.<\/em><\/li>\n<li data-start=\"1100\" data-end=\"1170\">Ograniczenie monitora wydajno\u015bci do u\u017cywanego serwera aplikacyjnego.<\/li>\n<li data-start=\"1174\" data-end=\"1244\">Ewentualne ograniczenie monitora wydajno\u015bci do w\u0142asnego u\u017cytkownika.<\/li>\n<li data-start=\"1248\" data-end=\"1280\">Zapisanie monitora wydajno\u015bci.<\/li>\n<li data-start=\"1284\" data-end=\"1316\">Aktywacja monitora wydajno\u015bci.<\/li>\n<li data-start=\"1320\" data-end=\"1353\">Wykonanie odpowiednich funkcji.<\/li>\n<li data-start=\"1357\" data-end=\"1391\">Zako\u0144czenie monitora wydajno\u015bci.<\/li>\n<li data-start=\"1396\" data-end=\"1432\">Analiza wynik\u00f3w monitora wydajno\u015bci.<\/li>\n<\/ol>\n<p data-start=\"1434\" data-end=\"1551\">Dalsze informacje znajduj\u0105 si\u0119 w artyku\u0142ach <em data-start=\"1479\" data-end=\"1500\">Monitory wydajno\u015bci<\/em> oraz <em data-start=\"1506\" data-end=\"1550\">Wykorzystywanie informacji wydajno\u015bciowych<\/em>.<\/p>\n<h6 data-start=\"1434\" data-end=\"1551\" id=\"protokoly-profilowania\" ><span class=\"ez-toc-section\" id=\"Protokoly_profilowania\"><\/span>Protoko\u0142y profilowania<span class=\"ez-toc-section-end\"><\/span><\/h6>\n<p data-start=\"1585\" data-end=\"1716\">Protoko\u0142y profilowania zliczaj\u0105, jak cz\u0119sto wybrane operacje us\u0142ugi persystencji s\u0105 wywo\u0142ywane oraz w jakim kontek\u015bcie (aplikacji).<\/p>\n<p data-start=\"1718\" data-end=\"1801\">Dalsze informacje na ten temat znajduj\u0105 si\u0119 w artykule <em data-start=\"1762\" data-end=\"1800\">Odczytywanie protoko\u0142\u00f3w profilowania<\/em>.<\/p>\n<h6 data-start=\"1718\" data-end=\"1801\" id=\"profilery-pamieci\" ><span class=\"ez-toc-section\" id=\"Profilery_pamieci\"><\/span>Profilery pami\u0119ci<span class=\"ez-toc-section-end\"><\/span><\/h6>\n<p data-start=\"1830\" data-end=\"2065\">Profilery pami\u0119ci w \u015brodowiskach deweloperskich Java (np. profiler pami\u0119ci narz\u0119dzia <em data-start=\"1915\" data-end=\"1928\">Optimize-It<\/em>) cz\u0119sto nie mog\u0105 by\u0107 wykorzystywane w systemach produkcyjnych, ale stanowi\u0105 jedyn\u0105 mo\u017cliwo\u015b\u0107 analizy problem\u00f3w pami\u0119ciowych w Comarch ERP Enterprise.<\/p>\n<h6 data-start=\"1830\" data-end=\"2065\" id=\"profilery-cpu\" ><span class=\"ez-toc-section\" id=\"Profilery_CPU\"><\/span>Profilery CPU<span class=\"ez-toc-section-end\"><\/span><\/h6>\n<p data-start=\"2090\" data-end=\"2623\">Profilery CPU w \u015brodowiskach deweloperskich Java (np. profiler CPU narz\u0119dzia <em data-start=\"2167\" data-end=\"2180\">Optimize-It<\/em>) cz\u0119sto nie mog\u0105 by\u0107 wykorzystywane w systemach produkcyjnych, a w systemach wielow\u0105tkowych\/wielosesyjnych, takich jak Comarch ERP Enterprise, cz\u0119sto maj\u0105 problem z przypisaniem pomiar\u00f3w do w\u0142a\u015bciwego kontekstu u\u017cytkownika. Ponadto niekt\u00f3re profilery Java zniekszta\u0142caj\u0105 w szczeg\u00f3lno\u015bci pomiary czasu, poniewa\u017c albo <em data-start=\"2509\" data-end=\"2518\">HotSpot<\/em> nie dzia\u0142a w pe\u0142nym zakresie, albo zbyt wiele niepotrzebnych punkt\u00f3w pomiarowych wyd\u0142u\u017ca czas wykonania.<\/p>\n<p data-start=\"2625\" data-end=\"2822\">W zwi\u0105zku z tym profilery Java w wielu przypadkach nie s\u0105 odpowiednie do pomiar\u00f3w w Comarch ERP Enterprise. Monitory wydajno\u015bci oraz protoko\u0142y profilowania zwykle dostarczaj\u0105 lepszych danych ni\u017c profilery Java.<\/p>\n<h6 data-start=\"2625\" data-end=\"2822\" id=\"wyprowadzanie-zapytan-bazodanowych\" ><span class=\"ez-toc-section\" id=\"Wyprowadzanie_zapytan_bazodanowych\"><\/span>Wyprowadzanie zapyta\u0144 bazodanowych<span class=\"ez-toc-section-end\"><\/span><\/h6>\n<p data-start=\"2868\" data-end=\"2970\">W trakcie rozwoju wykonywane zapytania bazodanowe mo\u017cna wyprowadza\u0107 za pomoc\u0105 nast\u0119puj\u0105cego polecenia.<\/p>\n<p data-start=\"2868\" data-end=\"2970\"><section class=\"document-alert-box warning\"><div class=\"document-alert-title\">Uwaga<\/div><div class=\"document-alert-content\">To wyprowadzanie nale\u017cy stosowa\u0107 wy\u0142\u0105cznie w systemie deweloperskim. Szczeg\u00f3lnie w systemie produkcyjnym wyprowadzanie mo\u017ce znacz\u0105co ograniczy\u0107 wydajno\u015b\u0107 serwera aplikacji.<\/div><\/section><\/p>\n<p data-start=\"2868\" data-end=\"2970\"><em>dbgcls -class:com.cisag.sys.kernel.sql.CisPreparedStatement<\/em><\/p>\n<p data-start=\"3236\" data-end=\"3382\">Za pomoc\u0105 opcjonalnego parametru <em>-level<\/em>\u00a0mo\u017cna ustawi\u0107 pr\u00f3g dotycz\u0105cy czasu wykonania, od kt\u00f3rego nast\u0119puje wyprowadzanie instrukcji bazodanowej.<\/p>\n<table style=\"width: 100%; border-collapse: collapse; border-style: outset; border-color: #000000; background-color: #ffffff;\">\n<tbody>\n<tr>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Parametr<\/strong><\/td>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Warto\u015b\u0107 progowa<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\">brak podanego poziomu lub <em>level:100<\/em><\/td>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\">brak warto\u015bci progowej<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><em>-level:2<\/em><\/td>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\">250 ms<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><em>-level:5 <\/em><\/td>\n<td style=\"width: 50%; border-style: outset; border-color: #000000; background-color: #ffffff;\">1000 ms<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4 data-start=\"3486\" data-end=\"3507\" id=\"indeksy\" ><span class=\"ez-toc-section\" id=\"Indeksy\"><\/span>Indeksy<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"51\" data-end=\"388\">Indeks jest struktur\u0105 dost\u0119pu, kt\u00f3ra mo\u017ce przyspieszy\u0107 dost\u0119p do pojedynczych wierszy tabeli. Indeks jest definiowany przez uporz\u0105dkowan\u0105 sekwencj\u0119 atrybut\u00f3w tabeli. Atrybuty te nazywane s\u0105 atrybutami indeksu. Szczeg\u00f3\u0142owe informacje dotycz\u0105ce wewn\u0119trznego dzia\u0142ania indeks\u00f3w mo\u017cna znale\u017a\u0107 w literaturze podstawowej dotycz\u0105cej baz danych.<\/p>\n<p data-start=\"390\" data-end=\"808\">Indeks zawiera (w uproszczeniu) wpis dla ka\u017cdego wiersza tabeli, dla kt\u00f3rej zosta\u0142 zdefiniowany. Wpis sk\u0142ada si\u0119 z warto\u015bci oraz odwo\u0142ania do przypisanego wiersza w tabeli. Indeks posiada struktur\u0119 dost\u0119pu, kt\u00f3ra umo\u017cliwia efektywne wyszukiwanie na podstawie warto\u015bci wpis\u00f3w indeksu. Na podstawie wpisu indeksu system zarz\u0105dzania baz\u0105 danych (DBMS) mo\u017ce w spos\u00f3b wydajny uzyska\u0107 dost\u0119p do odpowiedniego wiersza tabeli.<\/p>\n<p data-start=\"810\" data-end=\"1134\">Warto\u015b\u0107 wpisu indeksu wynika z warto\u015bci atrybut\u00f3w indeksu danego wiersza tabeli, na kt\u00f3ry wskazuje odwo\u0142anie. Indeksy stosowane w Comarch ERP Enterprise s\u0105 posortowane, tzn. wpisy indeksu s\u0105 uporz\u0105dkowane wed\u0142ug warto\u015bci. Opr\u00f3cz optymalizacji dost\u0119pu DBMS mo\u017ce r\u00f3wnie\u017c wykorzystywa\u0107 indeks do sortowania wynik\u00f3w zapytania.<\/p>\n<p data-start=\"810\" data-end=\"1134\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\"><\/p>\n<p data-start=\"810\" data-end=\"1134\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41929 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja.png\" alt=\"\" width=\"581\" height=\"201\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja.png 581w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja-300x104.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja-50x17.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja-320x111.png 320w\" sizes=\"auto, (max-width: 581px) 100vw, 581px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"1136\" data-end=\"1187\"><em>Przyk\u0142ad tabeli z dwoma indeksami<\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\">Tabela 1 w tym przyk\u0142adzie posiada dwa indeksy. Indeks BK (<em data-start=\"1248\" data-end=\"1262\">Business Key<\/em>) jest zdefiniowany na atrybutach <em data-start=\"1296\" data-end=\"1302\">Type<\/em> oraz <em data-start=\"1308\" data-end=\"1314\">Code<\/em>, natomiast indeks PK (<em data-start=\"1337\" data-end=\"1350\">Primary Key<\/em>) na atrybucie <em data-start=\"1365\" data-end=\"1371\">Guid<\/em>. Ka\u017cdy wpis indeksu wskazuje na jeden wiersz tabeli.<\/div><\/section><\/p>\n<h5 data-start=\"1136\" data-end=\"1187\" id=\"odczyt-z-wykorzystaniem-indeksu\" ><span class=\"ez-toc-section\" id=\"Odczyt_z_wykorzystaniem_indeksu\"><\/span>Odczyt z wykorzystaniem indeksu<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"1136\" data-end=\"1187\">Za pomoc\u0105 indeksu mo\u017cna wybiera\u0107 okre\u015blone wiersze tabeli. Czas wyszukiwania wpisu w indeksie mie\u015bci si\u0119 w <em>O(log(n))<\/em>, co oznacza, \u017ce wyszukiwanie zazwyczaj wymaga czasu logarytmicznego (<em data-start=\"1653\" data-end=\"1665\">index scan<\/em>).<br data-start=\"1667\" data-end=\"1670\" \/>W przeciwie\u0144stwie do tego, czas wyszukiwania wpisu bezpo\u015brednio w tabeli mie\u015bci si\u0119 w <em>O(n)<\/em>, czyli jest liniowy (<em data-start=\"1782\" data-end=\"1799\">full table scan<\/em>).<\/p>\n<p data-start=\"1136\" data-end=\"1187\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\"><\/p>\n<table style=\"width: 100%; border-collapse: collapse; border-style: outset; border-color: #000000; background-color: #ffffff;\">\n<tbody>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Liczba rekord\u00f3w<\/strong><\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Czas <em data-start=\"1843\" data-end=\"1860\">full table scan<\/em><\/strong><\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Czas <em data-start=\"1868\" data-end=\"1880\">index scan<\/em><\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,1 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,01 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10.000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">1 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,02 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">1.000.000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,03 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100.000.000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,04 s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p data-start=\"2063\" data-end=\"2281\">Im wi\u0119cej wierszy zawiera tabela, tym wi\u0119ksza jest przewaga czasowa dost\u0119pu z u\u017cyciem indeksu. Przyk\u0142ad ten pokazuje, \u017ce dost\u0119p do du\u017cej ilo\u015bci danych bez wykorzystania indeksu (<em data-start=\"2241\" data-end=\"2258\">full table scan<\/em>) jest nieakceptowalny.<\/div><\/section><\/p>\n<p data-start=\"2283\" data-end=\"2522\">Liczba atrybut\u00f3w indeksu (oraz ich rozmiar) ma wp\u0142yw na czas trwania <em data-start=\"2352\" data-end=\"2364\">index scan<\/em>. Dost\u0119p do indeksu z pi\u0119cioma atrybutami jest wolniejszy ni\u017c do indeksu z jednym atrybutem. Z tego powodu indeksy nie powinny obejmowa\u0107 zbyt wielu atrybut\u00f3w.<\/p>\n<p data-start=\"2524\" data-end=\"2912\">Indeks mo\u017ce zosta\u0107 wykorzystany w zapytaniu tylko wtedy, gdy pierwsze <em data-start=\"2594\" data-end=\"2597\">n<\/em> atrybut\u00f3w indeksu jest w zapytaniu ograniczonych operatorem <em>=<\/em>. Por\u00f3wnania atrybut\u00f3w indeksu powinny by\u0107 po\u0142\u0105czone operatorem <em>AND<\/em> oraz wyst\u0119powa\u0107 w tej samej kolejno\u015bci, co w definicji indeksu. Z\u0142o\u017cone zagnie\u017cd\u017cenia oraz kombinacje <em>AND<\/em> i <em>OR<\/em> utrudniaj\u0105 optymalizatorowi rozpoznanie mo\u017cliwo\u015bci u\u017cycia indeksu.<\/p>\n<p data-start=\"2524\" data-end=\"2912\"><em>SELECT * FROM Tabelle1 WHERE guid=\u20193BB8\u2019 <\/em><\/p>\n<p data-start=\"2524\" data-end=\"2912\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41931 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2.png\" alt=\"\" width=\"731\" height=\"201\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2.png 731w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2-300x82.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2-50x14.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2-600x165.png 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_2-320x88.png 320w\" sizes=\"auto, (max-width: 731px) 100vw, 731px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"2524\" data-end=\"2912\"><em>Przyk\u0142ad dost\u0119pu z wykorzystaniem wszystkich atrybut\u00f3w indeksu<\/em><\/p>\n<p data-start=\"2524\" data-end=\"2912\">Zapytanie mo\u017ce wykorzysta\u0107 indeks <em data-start=\"3065\" data-end=\"3074\">IndexPK<\/em>, dlatego jego z\u0142o\u017cono\u015b\u0107 czasowa wynosi <em>O(log(n))<\/em>.<\/p>\n<div class=\"flex flex-col text-sm pb-25\">\n<article class=\"text-token-text-primary w-full focus:outline-none [--shadow-height:45px] has-data-writing-block:pointer-events-none has-data-writing-block:-mt-(--shadow-height) has-data-writing-block:pt-(--shadow-height) [&amp;:has([data-writing-block])&gt;*]:pointer-events-auto scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]\" dir=\"auto\" tabindex=\"-1\" data-turn-id=\"e2006342-286d-4654-989f-7b0180a05d83\" data-testid=\"conversation-turn-12\" data-scroll-anchor=\"true\" data-turn=\"assistant\">\n<div class=\"text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] @w-sm\/main:[--thread-content-margin:--spacing(6)] @w-lg\/main:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:40rem] @w-lg\/main:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group\/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\" tabindex=\"-1\">\n<div class=\"flex max-w-full flex-col grow\">\n<div class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&amp;]:mt-1\" dir=\"auto\" data-message-author-role=\"assistant\" data-message-id=\"fbe857a9-22a7-4859-9a62-6bb1c0e1624b\" data-message-model-slug=\"gpt-5-2-thinking\">\n<div class=\"flex w-full flex-col gap-1 empty:hidden first:pt-[1px]\">\n<div class=\"markdown prose dark:prose-invert w-full break-words dark markdown-new-styling\">\n<p data-start=\"0\" data-end=\"107\" data-is-last-node=\"\" data-is-only-node=\"\">W poni\u017cszym zapytaniu mo\u017ce zosta\u0107 u\u017cyty indeks <em data-start=\"47\" data-end=\"56\">IndexBK<\/em>, poniewa\u017c <em data-start=\"67\" data-end=\"73\">type<\/em> jest pierwszym atrybutem indeksu:<\/p>\n<p data-start=\"0\" data-end=\"107\" data-is-last-node=\"\" data-is-only-node=\"\"><em>SELECT * FROM Tabelle1 WHERE type=\u2019100\u2019<\/em><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/article>\n<\/div>\n<p data-start=\"2524\" data-end=\"2912\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41933 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3.png\" alt=\"\" width=\"731\" height=\"201\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3.png 731w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3-300x82.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3-50x14.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3-600x165.png 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_3-320x88.png 320w\" sizes=\"auto, (max-width: 731px) 100vw, 731px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"2524\" data-end=\"2912\"><em>Przyk\u0142ad dost\u0119pu z wykorzystaniem pierwszych atrybut\u00f3w indeksu<\/em><\/p>\n<p data-start=\"2524\" data-end=\"2912\">Natomiast w poni\u017cszym zapytaniu konieczne jest wykonanie <em data-start=\"57\" data-end=\"74\">full table scan<\/em>, poniewa\u017c indeks <em data-start=\"92\" data-end=\"101\">IndexBK<\/em> nie rozpoczyna si\u0119 od atrybutu <em data-start=\"133\" data-end=\"139\">code<\/em>:<\/p>\n<p data-start=\"2524\" data-end=\"2912\"><em>SELECT * FROM Tabelle1 WHERE code=\u2019AB\u2019 <\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41934 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4.png\" alt=\"\" width=\"731\" height=\"201\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4.png 731w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4-300x82.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4-50x14.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4-600x165.png 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Kopia-Optymalizacja_4-320x88.png 320w\" sizes=\"auto, (max-width: 731px) 100vw, 731px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"1136\" data-end=\"1187\"><em>Przyk\u0142ad full table scan<\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\">W poni\u017cszym zapytaniu mo\u017ce zosta\u0107 u\u017cyty indeks <em data-start=\"47\" data-end=\"56\">IndexBK<\/em>, poniewa\u017c do selekcji wykorzystywany jest pierwszy atrybut indeksu (<em data-start=\"125\" data-end=\"131\">type<\/em>), a wszystkie atrybuty indeksu zosta\u0142y podane w klauzuli <em>ORDER BY<\/em> w poprawnej kolejno\u015bci:<\/p>\n<p data-start=\"1136\" data-end=\"1187\"><em>SELECT * FROM Tabelle1 WHERE type=\u2019100\u2019 ORDER BY type, code<\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41946 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9.png\" alt=\"\" width=\"749\" height=\"201\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9.png 749w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9-300x81.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9-50x13.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9-600x161.png 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_9-320x86.png 320w\" sizes=\"auto, (max-width: 749px) 100vw, 749px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"1136\" data-end=\"1187\"><em>Przyk\u0142ad sortowania z wykorzystaniem indeksu<\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\">Natomiast w poni\u017cszym zapytaniu indeks <em data-start=\"39\" data-end=\"48\">IndexBK<\/em> mo\u017ce zosta\u0107 u\u017cyty wy\u0142\u0105cznie do selekcji, a nie do sortowania, poniewa\u017c sortowanie nie obejmuje pierwszych <em data-start=\"155\" data-end=\"158\">n<\/em> atrybut\u00f3w indeksu.<\/p>\n<p data-start=\"1136\" data-end=\"1187\"><em>SELECT * FROM Tabelle1 WHERE type=\u2019100\u2019 OR type=\u2019200\u2019 ORDER BY code<\/em><\/p>\n<p data-start=\"1136\" data-end=\"1187\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41948 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10.png\" alt=\"\" width=\"741\" height=\"460\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10.png 741w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10-300x186.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10-50x31.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10-600x372.png 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_10-320x199.png 320w\" sizes=\"auto, (max-width: 741px) 100vw, 741px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"1136\" data-end=\"1187\"><em>Przyk\u0142ad sortowania w tabeli tymczasowej<\/em><\/p>\n<h5 data-start=\"1136\" data-end=\"1187\" id=\"wybor-atrybutow-indeksu\" ><span class=\"ez-toc-section\" id=\"Wybor_atrybutow_indeksu\"><\/span>Wyb\u00f3r atrybut\u00f3w indeksu<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"1136\" data-end=\"1187\">Indeks mo\u017ce by\u0107 sensownie wykorzystywany przez DBMS do selekcji tylko wtedy, gdy w istotny spos\u00f3b ogranicza liczb\u0119 mo\u017cliwych wierszy wynikowych. Je\u017celi na przyk\u0142ad indeks ogranicza liczb\u0119 potencjalnych wierszy tabeli jedynie o 50%, DBMS najprawdopodobniej nie b\u0119dzie go u\u017cywa\u0107, poniewa\u017c w takim przypadku <em data-start=\"340\" data-end=\"357\">full table scan<\/em> jest korzystniejszy ni\u017c <em data-start=\"382\" data-end=\"394\">index scan<\/em>.<\/p>\n<p data-start=\"1136\" data-end=\"1187\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Indeks sk\u0142adaj\u0105cy si\u0119 wy\u0142\u0105cznie z atrybutu <em data-start=\"456\" data-end=\"462\">P\u0142e\u0107<\/em> nie jest uzasadniony.<\/div><\/section><\/p>\n<p data-start=\"486\" data-end=\"752\">Indeksy nale\u017cy zawsze definiowa\u0107 w taki spos\u00f3b, aby pojedynczy wpis indeksu odnosi\u0142 si\u0119 do jak najmniejszej liczby wierszy tabeli. Im wi\u0119ksza jest r\u00f3\u017cnica pomi\u0119dzy liczb\u0105 wpis\u00f3w indeksu a liczb\u0105 wierszy tabeli, tym bardziej w\u0105tpliwa jest przydatno\u015b\u0107 takiego indeksu.<\/p>\n<p data-start=\"754\" data-end=\"880\">Wyj\u0105tkiem od powy\u017cszej regu\u0142y jest sytuacja, w kt\u00f3rej wykorzystanie warto\u015bci atrybutu indeksu nie jest r\u00f3wnomiernie roz\u0142o\u017cone.<\/p>\n<p data-start=\"754\" data-end=\"880\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u017celi 95% wszystkich zam\u00f3wie\u0144 jest zrealizowanych, a 5% znajduje si\u0119 w statusie innym ni\u017c zrealizowany, indeks z pojedynczym atrybutem <em data-start=\"1034\" data-end=\"1042\">Status<\/em> jest uzasadniony.<\/div><\/section><\/p>\n<p data-start=\"754\" data-end=\"880\">Baza danych zazwyczaj wykorzystuje w zapytaniu tylko jeden indeks na tabel\u0119 do selekcji. Tworzenie osobnego indeksu (o niskiej selektywno\u015bci) dla ka\u017cdego atrybutu nie ma sensu. Nale\u017cy zidentyfikowa\u0107 kombinacje atrybut\u00f3w o wysokiej selektywno\u015bci, kt\u00f3re s\u0105 wykorzystywane w jak najwi\u0119kszej liczbie istotnych zapyta\u0144, i dla nich definiowa\u0107 indeksy. W tym celu nale\u017cy korzysta\u0107 z funkcji monitorowania DBMS.<\/p>\n<h5 data-start=\"754\" data-end=\"880\" id=\"zapis-z-wykorzystaniem-indeksu\" ><span class=\"ez-toc-section\" id=\"Zapis_z_wykorzystaniem_indeksu\"><\/span>Zapis z wykorzystaniem indeksu<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"754\" data-end=\"880\">Podczas wstawiania, modyfikowania i usuwania wierszy tabeli wszystkie indeksy zdefiniowane dla danej tabeli musz\u0105 zosta\u0107 zaktualizowane. Czas potrzebny na aktualizacj\u0119 jednego indeksu mie\u015bci si\u0119 w <em>O(log(n))<\/em>. W zwi\u0105zku z tym czas wstawiania, modyfikowania i usuwania wierszy tabeli ro\u015bnie liniowo wraz z liczb\u0105 indeks\u00f3w.<\/p>\n<p data-start=\"754\" data-end=\"880\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\"><\/p>\n<table style=\"width: 100%; border-collapse: collapse; border-style: outset; border-color: #000000; background-color: #ffffff;\">\n<tbody>\n<tr>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Liczba rekord\u00f3w<\/strong><\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Zmiana przy 1 indeksie<\/strong><\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Zmiana przy 2 indeksach<\/strong><\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Zmiana przy 4 indeksach<\/strong><\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Zmiana przy 8 indeksach<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">5 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">20 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">40 ms<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 000<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">20 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">40 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">80 ms<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">1 000 000<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">15 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">30 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">60 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">160 ms<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100 000 000<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">20 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">40 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">80 ms<\/td>\n<td style=\"width: 20%; border-style: outset; border-color: #000000; background-color: #ffffff;\">320 ms<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p data-start=\"754\" data-end=\"880\"><\/div><\/section><\/p>\n<p data-start=\"754\" data-end=\"880\">W przypadku modyfikacji danych aktualizacja indeks\u00f3w jest relatywnie czasoch\u0142onna. Dlatego dla danych cz\u0119sto zmienianych (np. danych ruchowych) nie nale\u017cy definiowa\u0107 zbyt wielu indeks\u00f3w dla jednej tabeli. Natomiast w przypadku tabel, kt\u00f3rych dane zmieniaj\u0105 si\u0119 rzadko (np. dane podstawowe), zwi\u0119kszony nak\u0142ad czasowy zwi\u0105zany z aktualizacj\u0105 indeks\u00f3w nie ma istotnego negatywnego wp\u0142ywu.<\/p>\n<h5 data-start=\"754\" data-end=\"880\" id=\"relacje\" ><span class=\"ez-toc-section\" id=\"Relacje\"><\/span>Relacje<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"94\">Relacje w Comarch ERP Enterprise s\u0105 niemal zawsze definiowane za pomoc\u0105 klucza podstawowego.<\/p>\n<p data-start=\"96\" data-end=\"370\">W relacjach typu 1:1 klucz podstawowy instancji docelowego obiektu biznesowego jest zapisywany w instancji \u017ar\u00f3d\u0142owego obiektu biznesowego. Podczas odpytywania relacji do instancji docelowej przy dost\u0119pie do bazy danych mo\u017ce zosta\u0107 u\u017cyty indeks podstawowy obiektu docelowego.<\/p>\n<p data-start=\"372\" data-end=\"726\" data-is-last-node=\"\" data-is-only-node=\"\">W relacjach typu 1:n klucz podstawowy instancji \u017ar\u00f3d\u0142owego obiektu biznesowego jest zapisywany w instancji docelowego obiektu biznesowego. W modelu danych nale\u017cy bezwzgl\u0119dnie utworzy\u0107 indeks w docelowym obiekcie biznesowym, kt\u00f3ry w pe\u0142ni obejmuje kopie atrybut\u00f3w klucza podstawowego \u017ar\u00f3d\u0142owego obiektu biznesowego lub przynajmniej od nich si\u0119 rozpoczyna.<\/p>\n<p data-start=\"372\" data-end=\"726\" data-is-last-node=\"\" data-is-only-node=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41943 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_8.png\" alt=\"\" width=\"536\" height=\"415\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_8.png 536w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_8-300x232.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_8-50x39.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_8-320x248.png 320w\" sizes=\"auto, (max-width: 536px) 100vw, 536px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"372\" data-end=\"726\" data-is-last-node=\"\" data-is-only-node=\"\"><em>Przyk\u0142adowe tworzenie indeks\u00f3w dla relacji 1:1 oraz 1:n<\/em><\/p>\n<p data-start=\"58\" data-end=\"370\">Indeks <em data-start=\"65\" data-end=\"69\">PK<\/em> w obiekcie biznesowym <em data-start=\"92\" data-end=\"105\">OrderDetail<\/em> rozpoczyna si\u0119 od atrybutu <em data-start=\"133\" data-end=\"141\">header<\/em>, kt\u00f3ry zawiera warto\u015b\u0107 atrybutu <em data-start=\"174\" data-end=\"180\">guid<\/em> powi\u0105zanego obiektu <em data-start=\"201\" data-end=\"208\">Order<\/em>. Dzi\u0119ki temu podczas rozwi\u0105zywania relacji <em data-start=\"252\" data-end=\"266\">OrderDetail<\/em>\u00a0mo\u017ce zosta\u0107 u\u017cyty indeks <em data-start=\"292\" data-end=\"296\">PK<\/em> obiektu biznesowego <em data-start=\"317\" data-end=\"330\">OrderDetail<\/em> w celu ustalenia powi\u0105zanych instancji.<\/p>\n<p data-start=\"372\" data-end=\"566\">W szczeg\u00f3lno\u015bci w przypadku obiekt\u00f3w zale\u017cnych (<em data-start=\"420\" data-end=\"432\">Dependents<\/em>) zasadne mo\u017ce by\u0107 wykorzystanie klucza podstawowego encji (tj. jej GUID) jako pierwszej cz\u0119\u015bci klucza podstawowego obiektu zale\u017cnego.<\/p>\n<p data-start=\"568\" data-end=\"946\">Klucz podstawowy ma w niekt\u00f3rych bazach danych szczeg\u00f3lne znaczenie. W cz\u0119\u015bci system\u00f3w bazodanowych wiersze tabeli s\u0105 fizycznie przechowywane zgodnie z kolejno\u015bci\u0105 sortowania w indeksie (klaster). Ma to t\u0119 zalet\u0119, \u017ce podczas <em data-start=\"793\" data-end=\"805\">index scan<\/em> dost\u0119p do wierszy tabeli odbywa si\u0119 sekwencyjnie, dzi\u0119ki czemu DBMS musi za\u0142adowa\u0107 znacznie mniej danych w celu obliczenia wyniku zapytania.<\/p>\n<h5 data-start=\"568\" data-end=\"946\" id=\"dane-ruchowe\" ><span class=\"ez-toc-section\" id=\"Dane_ruchowe\"><\/span>Dane ruchowe<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"313\">Dane ruchowe cz\u0119sto dziel\u0105 si\u0119 na dane aktywne oraz dane historyczne. Przyk\u0142adowo wszystkie zam\u00f3wienia, kt\u00f3re maj\u0105 status inny ni\u017c zrealizowany, nale\u017c\u0105 do danych aktywnych, natomiast zam\u00f3wienia zrealizowane stanowi\u0105 raczej dane historyczne. Pomi\u0119dzy danymi aktywnymi a historycznymi wyst\u0119puj\u0105 nast\u0119puj\u0105ce r\u00f3\u017cnice:<\/p>\n<ul>\n<li data-start=\"317\" data-end=\"400\">wolumen danych aktywnych jest wyra\u017anie mniejszy ni\u017c wolumen danych historycznych,<\/li>\n<li data-start=\"403\" data-end=\"496\">na danych aktywnych w bie\u017c\u0105cej eksploatacji cz\u0119sto wykonywane s\u0105 operacje odczytu i zapisu,<\/li>\n<li data-start=\"499\" data-end=\"608\">na danych historycznych wykonywane s\u0105 ju\u017c tylko operacje odczytu, natomiast operacje zapisu wyst\u0119puj\u0105 rzadko.<\/li>\n<\/ul>\n<p data-start=\"610\" data-end=\"877\">Rozdzielenie danych ruchowych na aktywne i historyczne jest cz\u0119sto realizowane za pomoc\u0105 atrybutu statusu w nag\u0142\u00f3wku encji. Je\u017celi tworzone s\u0105 indeksy w celu poprawy wydajno\u015bci, atrybut statusu powinien \u2013 o ile to mo\u017cliwe \u2013 znajdowa\u0107 si\u0119 na pierwszej pozycji indeksu.<\/p>\n<h5 data-start=\"610\" data-end=\"877\" id=\"dane-podstawowe\" ><span class=\"ez-toc-section\" id=\"Dane_podstawowe\"><\/span>Dane podstawowe<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"610\" data-end=\"877\">W przypadku danych podstawowych wyst\u0119puje bardzo du\u017co operacji odczytu, natomiast stosunkowo niewiele operacji zapisu. Wolumen danych podstawowych w du\u017cym stopniu zale\u017cy od konkretnego przypadku u\u017cycia.<\/p>\n<p data-start=\"610\" data-end=\"877\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Jeden klient ma 100 artyku\u0142\u00f3w, natomiast inny klient mo\u017ce mie\u0107 nawet 100 000 artyku\u0142\u00f3w.<\/div><\/section><\/p>\n<h4 data-start=\"610\" data-end=\"877\" id=\"order-by\" ><span class=\"ez-toc-section\" id=\"ORDER_BY\"><\/span>ORDER BY<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"0\" data-end=\"435\">Je\u017celi do sortowania wyniku zapytania nie mo\u017ce zosta\u0107 u\u017cyty \u017caden indeks, zapotrzebowanie czasowe sortowania wyniku wynosi <em>O(n\u00b7log(n))<\/em>. W praktyce sortowanie ma\u0142ych zbior\u00f3w danych jest zwykle nieproporcjonalnie szybsze ni\u017c sortowanie du\u017cych zbior\u00f3w danych. Ma\u0142e zbiory danych (np. &lt; 1 MB) DBMS mo\u017ce sortowa\u0107 w pami\u0119ci operacyjnej. W przypadku du\u017cych zbior\u00f3w danych mo\u017ce by\u0107 konieczne tymczasowe zapisywanie wynik\u00f3w sortowania na dysku.<\/p>\n<p data-start=\"437\" data-end=\"729\">DBMS musi obliczy\u0107 pe\u0142ny wynik zapytania, zanim b\u0119dzie m\u00f3g\u0142 zwr\u00f3ci\u0107 pierwszy rekord posortowanego zbioru wynik\u00f3w. Oznacza to w szczeg\u00f3lno\u015bci, \u017ce wynik zapytania musi zosta\u0107 tymczasowo buforowany w bazie danych. R\u00f3wnie\u017c z tego powodu sortowanie du\u017cych zbior\u00f3w wynik\u00f3w jest bardzo czasoch\u0142onne.<\/p>\n<p data-start=\"731\" data-end=\"893\">Je\u017celi do sortowania mo\u017ce zosta\u0107 u\u017cyty indeks, zapotrzebowanie czasowe sortowania wynosi <em>O(n)<\/em>. Oznacza to, \u017ce czas ro\u015bnie liniowo wraz z liczb\u0105 rekord\u00f3w w wyniku.<\/p>\n<p data-start=\"731\" data-end=\"893\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\"><\/p>\n<table style=\"width: 100%; border-collapse: collapse; border-style: outset; border-color: #000000; background-color: #ffffff;\">\n<tbody>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Liczba rekord\u00f3w<\/strong><\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Czas sortowania bez indeksu<\/strong><\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\"><strong>Czas sortowania z indeksem<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,2 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">0,2 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">10 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">2 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">1 000 000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">150 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">20 s<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">100 000 000<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">2000 s<\/td>\n<td style=\"width: 33.3333%; border-style: outset; border-color: #000000; background-color: #ffffff;\">200 s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p data-start=\"731\" data-end=\"893\"><\/div><\/section><\/p>\n<p data-start=\"731\" data-end=\"893\">Je\u017celi sortowanie jest konieczne, nale\u017cy zatem albo utrzymywa\u0107 zbi\u00f3r wynik\u00f3w na tyle ma\u0142y, aby sortowanie nie by\u0142o nadmiernie kosztowne, albo utworzy\u0107 indeks, kt\u00f3ry mo\u017ce zosta\u0107 wykorzystany do sortowania.<\/p>\n<h4 data-start=\"731\" data-end=\"893\" id=\"group-by\" ><span class=\"ez-toc-section\" id=\"GROUP_BY\"><\/span>GROUP BY<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"731\" data-end=\"893\">Zapotrzebowanie czasowe przy pobieraniu pe\u0142nego zbioru wynik\u00f3w zapytania z klauzul\u0105 <em>GROUP BY<\/em> wynosi \u2013 podobnie jak w przypadku sortowania \u2013 <em>O(n\u00b7log(n))<\/em>. Tak jak przy sortowaniu, r\u00f3wnie\u017c dla <em>GROUP BY <\/em>mo\u017ce zosta\u0107 u\u017cyty indeks, je\u017celi klauzula <em>GROUP BY <\/em>sk\u0142ada si\u0119 z sekwencji pierwszych <em data-start=\"308\" data-end=\"311\">n<\/em> atrybut\u00f3w indeksu.<\/p>\n<h4 data-start=\"731\" data-end=\"893\" id=\"distinct\" ><span class=\"ez-toc-section\" id=\"DISTINCT\"><\/span>DISTINCT<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"731\" data-end=\"893\">Zapotrzebowanie czasowe przy pobieraniu pe\u0142nego zbioru wynik\u00f3w zapytania z klauzul\u0105 <em>DISTINCT<\/em> wynosi \u2013 podobnie jak w przypadku sortowania \u2013<em> O(n\u00b7log(n))<\/em>. W przypadku <em>DISTINCT <\/em>nie zawsze jest jednak konieczne obliczenie pe\u0142nego wyniku zapytania przed zwr\u00f3ceniem pierwszego wiersza wynikowego.<\/p>\n<h3 data-start=\"731\" data-end=\"893\" id=\"optymalizacje\" ><span class=\"ez-toc-section\" id=\"Optymalizacje\"><\/span>Optymalizacje<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h4 data-start=\"731\" data-end=\"893\" id=\"dostep-do-bazy-danych\" ><span class=\"ez-toc-section\" id=\"Dostep_do_bazy_danych\"><\/span>Dost\u0119p do bazy danych<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"707\" data-end=\"805\">Prawie wszystkie aplikacje zawieraj\u0105 niekt\u00f3re lub wszystkie z nast\u0119puj\u0105cych cz\u0119\u015bci funkcjonalnych:<\/p>\n<ul>\n<li data-start=\"808\" data-end=\"838\">odczyt danych z bazy danych,<\/li>\n<li data-start=\"841\" data-end=\"864\">przetwarzanie danych,<\/li>\n<li data-start=\"867\" data-end=\"897\">zapis danych do bazy danych,<\/li>\n<li data-start=\"900\" data-end=\"920\">wy\u015bwietlanie danych.<\/li>\n<\/ul>\n<p data-start=\"922\" data-end=\"1075\">W wi\u0119kszo\u015bci aplikacji odczytywanych jest wi\u0119cej danych ni\u017c zapisywanych. Odczyt i zapis danych z bazy danych cz\u0119sto zajmuj\u0105 najwi\u0119cej czasu w aplikacji.<\/p>\n<p data-start=\"1077\" data-end=\"1240\">O ile nie s\u0105 wykonywane zb\u0119dne operacje zapisu, a rozmiar transakcji nie jest ani zbyt ma\u0142y, ani zbyt du\u017cy, potencja\u0142 optymalizacji operacji zapisu jest niewielki.<\/p>\n<h5 data-start=\"1077\" data-end=\"1240\" id=\"znaczenie-wspoldzielonego-cache\" ><span class=\"ez-toc-section\" id=\"Znaczenie_wspoldzielonego_cache\"><\/span>Znaczenie wsp\u00f3\u0142dzielonego cache<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"1290\" data-end=\"1647\">Operacje odczytu bardzo cz\u0119sto wymagaj\u0105 najwi\u0119cej czasu. Dost\u0119p do bazy danych jest w por\u00f3wnaniu z dost\u0119pem do danych znajduj\u0105cych si\u0119 w serwerze aplikacyjnym znacznie wolniejszy. Z tego powodu Comarch ERP Enterprise posiada wsp\u00f3\u0142dzielony cache (<em data-start=\"263\" data-end=\"277\">shared cache)<\/em>, kt\u00f3ry umo\u017cliwia ponowne wykorzystywanie cz\u0119sto odczytywanych instancji obiekt\u00f3w biznesowych.<\/p>\n<p data-start=\"1649\" data-end=\"1770\" data-is-last-node=\"\" data-is-only-node=\"\">Wsp\u00f3\u0142dzielony cache ma ograniczony rozmiar i mo\u017ce przechowywa\u0107 w pami\u0119ci okre\u015blon\u0105 liczb\u0119 instancji obiekt\u00f3w biznesowych.<\/p>\n<p data-start=\"1649\" data-end=\"1770\" data-is-last-node=\"\" data-is-only-node=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41942 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_7.png\" alt=\"\" width=\"442\" height=\"342\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_7.png 442w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_7-300x232.png 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_7-50x39.png 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_7-320x248.png 320w\" sizes=\"auto, (max-width: 442px) 100vw, 442px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"1649\" data-end=\"1770\" data-is-last-node=\"\" data-is-only-node=\"\"><em>Czas dost\u0119pu do obiektu biznesowego<\/em><\/p>\n<p data-start=\"1649\" data-end=\"1770\" data-is-last-node=\"\" data-is-only-node=\"\">Dost\u0119p do bazy danych mo\u017ce by\u0107 ponad 50-krotnie wolniejszy ni\u017c dost\u0119p do wsp\u00f3\u0142dzielonego cache. Wsp\u00f3\u0142czynnik <em data-start=\"150\" data-end=\"166\">cache hit rate<\/em> okre\u015bla, przy jakim procencie odwo\u0142a\u0144 \u017c\u0105dana instancja obiektu biznesowego zosta\u0142a znaleziona w <em data-start=\"263\" data-end=\"277\">shared cache<\/em>.<\/p>\n<p data-start=\"1649\" data-end=\"1770\" data-is-last-node=\"\" data-is-only-node=\"\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Zak\u0142adaj\u0105c, \u017ce dost\u0119p do bazy danych jest 50 razy wolniejszy ni\u017c dost\u0119p do <em data-start=\"371\" data-end=\"385\">shared cache<\/em>, a dla danego obiektu biznesowego <em data-start=\"420\" data-end=\"436\">cache hit rate<\/em> wynosi 95%, oznacza to, \u017ce 95% wszystkich odczyt\u00f3w pojedynczej instancji obiektu biznesowego jest obs\u0142ugiwanych przez <em data-start=\"555\" data-end=\"569\">shared cache<\/em>, natomiast 5% odczyt\u00f3w wymaga dost\u0119pu do bazy danych. Z tego wynika, \u017ce operacje dost\u0119pu do bazy danych odpowiadaj\u0105 za 72% \u015bredniego czasu dost\u0119pu.<\/div><\/section><\/p>\n<p data-start=\"719\" data-end=\"1005\">Ze wzgl\u0119du na du\u017c\u0105 r\u00f3\u017cnic\u0119 pomi\u0119dzy czasem dost\u0119pu do szybkiego <em data-start=\"785\" data-end=\"799\">shared cache<\/em> a wolnej bazy danych, nawet przy pozornie wysokim <em data-start=\"852\" data-end=\"868\">cache hit rate<\/em> przekraczaj\u0105cym 90% to faktycznie wykonywane dost\u0119py do bazy danych stanowi\u0105 decyduj\u0105cy czynnik wp\u0142ywaj\u0105cy na \u015bredni czas przetwarzania.<\/p>\n<p data-start=\"1007\" data-end=\"1382\"><em data-start=\"1007\" data-end=\"1021\">Shared cache<\/em> przechowuje wy\u0142\u0105cznie istniej\u0105ce obiekty i zasadniczo nie zapami\u0119tuje, kt\u00f3re obiekty zosta\u0142y usuni\u0119te lub nie istniej\u0105. Oznacza to, \u017ce gdy metoda <em>getObject<\/em> zostanie wywo\u0142ana z kluczem, dla kt\u00f3rego nie istnieje \u017cadna instancja obiektu biznesowego, us\u0142uga persystencji nie mo\u017ce obs\u0142u\u017cy\u0107 takiego \u017c\u0105dania z <em data-start=\"1327\" data-end=\"1341\">shared cache<\/em> i musi wykona\u0107 zapytanie do bazy danych.<\/p>\n<p data-start=\"1384\" data-end=\"1589\">W szczeg\u00f3lno\u015bci podczas projektowania lub rozszerzania obiekt\u00f3w biznesowych nale\u017cy zadba\u0107 o to, aby w relacjach typu 1:1 istnienie obiektu docelowego mog\u0142o zosta\u0107 wywnioskowane ze stanu obiektu \u017ar\u00f3d\u0142owego.<\/p>\n<h5 data-start=\"1384\" data-end=\"1589\" id=\"wykorzystanie-getobjectarray\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_getObjectArray\"><\/span>Wykorzystanie <em>getObjectArray<\/em><span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"34\" data-end=\"162\">Dost\u0119p odczytowy do instancji obiektu biznesowego w bazie danych z Comarch ERP Enterprise przebiega przez nast\u0119puj\u0105ce warstwy:<\/p>\n<p data-start=\"34\" data-end=\"162\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41940 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_6.png\" alt=\"\" width=\"241\" height=\"190\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_6.png 241w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_6-50x39.png 50w\" sizes=\"auto, (max-width: 241px) 100vw, 241px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"164\" data-end=\"212\"><em>R\u00f3\u017cne warstwy podczas dost\u0119pu do bazy danych<\/em><\/p>\n<p data-start=\"214\" data-end=\"423\">W pierwszym kroku dla operacji odczytu tworzona jest instrukcja SQL, kt\u00f3ra nast\u0119pnie jest przesy\u0142ana do bazy danych, tam wykonywana, a na podstawie wyniku zapytania tworzona jest instancja obiektu biznesowego:<\/p>\n<ul>\n<li data-start=\"427\" data-end=\"761\">nak\u0142ad czasowy potrzebny na zbudowanie zapytania oraz na utworzenie instancji obiektu biznesowego na podstawie wyniku zapytania zale\u017cy od liczby atrybut\u00f3w, jakie obejmuje obiekt biznesowy. Im wy\u017csza jest wydajno\u015b\u0107 CPU komputera, na kt\u00f3rym dzia\u0142a serwer aplikacyjny, tym mniejszy jest czas potrzebny na mapowanie obiektu biznesowego.<\/li>\n<li data-start=\"764\" data-end=\"1127\">nak\u0142ad czasowy zwi\u0105zany z komunikacj\u0105 r\u00f3wnie\u017c zale\u017cy od z\u0142o\u017cono\u015bci obiektu biznesowego. W przypadku komunikacji decyduj\u0105cym czynnikiem wp\u0142ywaj\u0105cym na czas jest rodzaj po\u0142\u0105czenia sieciowego pomi\u0119dzy serwerem aplikacyjnym a serwerem bazy danych. Je\u017celi serwer aplikacyjny i serwer bazy danych dzia\u0142aj\u0105 na tym samym komputerze, narzut komunikacyjny jest minimalny.<\/li>\n<li data-start=\"1130\" data-end=\"1418\">czas przetwarzania po stronie bazy danych zale\u017cy od wielu czynnik\u00f3w. Je\u017celi zapytanie zostanie obs\u0142u\u017cone z wewn\u0119trznego cache bazy danych, czas odpowiedzi mo\u017ce wynosi\u0107 zaledwie kilka milisekund. Je\u017celi konieczny jest dost\u0119p do dysk\u00f3w, wykonanie zapytania zajmuje zwykle nieco ponad 10 ms.<\/li>\n<\/ul>\n<p data-start=\"1420\" data-end=\"1666\">Je\u017celi metod\u0105 <em>getObject<\/em> odczytywanych jest <em data-start=\"1465\" data-end=\"1468\">n<\/em> instancji obiekt\u00f3w biznesowych, kt\u00f3re nie znajduj\u0105 si\u0119 w <em data-start=\"1526\" data-end=\"1540\">shared cache<\/em>, w\u00f3wczas <em data-start=\"1550\" data-end=\"1553\">n<\/em>-krotnie ponoszony jest koszt mapowania obiektu biznesowego, komunikacji oraz wykonania zapytania do bazy danych.<\/p>\n<p data-start=\"1668\" data-end=\"2005\">Metoda <em>getObjectArray <\/em>umo\u017cliwia odczyt wielu instancji obiekt\u00f3w biznesowych w ramach jednego zapytania do bazy danych. Dzi\u0119ki temu zmniejsza si\u0119 narzut komunikacyjny, poniewa\u017c zapytanie jest przesy\u0142ane do serwera bazy danych tylko raz, a wynik zapytania jest przekazywany jako jeden blok z serwera bazy danych do serwera aplikacyjnego.<\/p>\n<p data-start=\"2007\" data-end=\"2196\">Je\u017celi serwer bazy danych i serwer aplikacyjny nie dzia\u0142aj\u0105 na tym samym komputerze, zastosowanie metody <em>getObjectArray <\/em>mo\u017ce przyspieszy\u0107 odczyt danych w programie nawet do trzykrotno\u015bci.<\/p>\n<h5 data-start=\"2007\" data-end=\"2196\" id=\"wykorzystanie-insert\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_INSERT\"><\/span>Wykorzystanie <em>INSERT<\/em><span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"2235\" data-end=\"2560\">Przy u\u017cyciu flagi <em>CisObjectManager.INSERT<\/em> us\u0142uga persystencji nie sprawdza, czy obiekt ju\u017c istnieje w bazie danych. Podczas odczytu obiektu z u\u017cyciem <em>INSERT <\/em>us\u0142uga persystencji nie wykonuje dost\u0119pu do bazy danych. Je\u017celi jednak obiekt faktycznie istnieje w bazie danych, zastosowanie <em>INSERT <\/em>prowadzi do b\u0142\u0119du wykonania.<\/p>\n<p data-start=\"2562\" data-end=\"2848\">Je\u017celi nowe obiekty s\u0105 tworzone z u\u017cyciem flagi <em>READ_WRITE<\/em>, dla ka\u017cdego nowego obiektu konieczny jest odczyt z bazy danych w celu sprawdzenia, czy obiekt ju\u017c istnieje. Je\u017celi mo\u017cliwe jest u\u017cycie <em>INSERT<\/em>, operacja odczytu zostaje pomini\u0119ta, co prowadzi do istotnej oszcz\u0119dno\u015bci czasu.<\/p>\n<p data-start=\"2850\" data-end=\"3353\">Flaga <em>CisObjectManager.INSERT <\/em>powinna by\u0107 stosowana zawsze wtedy, gdy na podstawie przebiegu programu wiadomo, \u017ce tworzony obiekt nie istnieje jeszcze w bazie danych. W przypadku tworzenia nowych encji wystarczaj\u0105ce jest \u2013 o ile w og\u00f3le jest to konieczne \u2013 utworzenie g\u0142\u00f3wnego obiektu biznesowego encji z u\u017cyciem <em>READ_WRITE<\/em>. Wszystkie obiekty zale\u017cne (<em data-start=\"3206\" data-end=\"3218\">dependents<\/em>) encji mog\u0105 by\u0107 tworzone z u\u017cyciem <em>INSERT,<\/em>\u00a0o ile g\u0142\u00f3wny obiekt biznesowy nie jest jeszcze trwa\u0142y (nie jest zapisany w bazie danych).<\/p>\n<h5 data-start=\"2850\" data-end=\"3353\" id=\"stale-w-oql\" ><span class=\"ez-toc-section\" id=\"Stale_w_OQL\"><\/span>Sta\u0142e w OQL<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"440\">Nigdy nie nale\u017cy u\u017cywa\u0107 sta\u0142ych tekstowych jako parametr\u00f3w zapyta\u0144 w OQL, lecz zamiast tego stosowa\u0107 symbol zast\u0119pczy <em>?<\/em>. Ka\u017cda instrukcja OQL jest t\u0142umaczona na SQL. W tym celu instrukcja OQL jest parsowana, a nast\u0119pnie \u2013 z wykorzystaniem opis\u00f3w obiekt\u00f3w biznesowych \u2013 generowana jest instrukcja SQL. Poniewa\u017c takie t\u0142umaczenie mo\u017ce by\u0107 stosunkowo kosztowne, wygenerowane w ten spos\u00f3b instrukcje SQL s\u0105 przechowywane w pami\u0119ci podr\u0119cznej.<\/p>\n<p data-start=\"442\" data-end=\"1055\">Ka\u017cda instrukcja OQL, dla kt\u00f3rej w cache nie istnieje jeszcze odpowiadaj\u0105ca jej instrukcja SQL, musi zosta\u0107 przet\u0142umaczona od nowa. W praktyce warto\u015bci parametr\u00f3w zapyta\u0144 nie s\u0105 sta\u0142e. Je\u017celi zamiast symboli zast\u0119pczych <em>?<\/em> w instrukcji OQL u\u017cywane s\u0105 bezpo\u015brednio sta\u0142e tekstowe jako parametry zapytania, za ka\u017cdym razem powstaje nowa instrukcja OQL, kt\u00f3ra musi by\u0107 ponownie t\u0142umaczona na SQL. Dodatkowo ka\u017cda nowa instrukcja bazodanowa mo\u017ce powodowa\u0107 kolejne dost\u0119py do bazy danych zwi\u0105zane z monitorowaniem wydajno\u015bci. Z tych powod\u00f3w u\u017cywanie sta\u0142ych tekstowych jako parametr\u00f3w zapyta\u0144 w OQL jest niedozwolone.<\/p>\n<p data-start=\"1057\" data-end=\"1321\">Podczas komunikacji z baz\u0105 danych instrukcje SQL s\u0105 wielokrotnie wykorzystywane (<em>prepared statements)<\/em>. Je\u017celi parametry zapytania s\u0105 przekazywane jako sta\u0142e tekstowe, wzrasta r\u00f3wnie\u017c obci\u0105\u017cenie bazy danych, poniewa\u017c prepared statements nie mog\u0105 by\u0107 ponownie u\u017cyte.<\/p>\n<p data-start=\"1057\" data-end=\"1321\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Niepoprawny przyk\u0142ad u\u017cycia parametr\u00f3w zapytania w OQL:<\/p>\n<p><em>CisObjectIterator i=om.getObjectIterator(<\/em><\/p>\n<p><em>\u201cSELECT FROM com.cisag.app.general.obj.Item i WHERE \u201c+<\/em><\/p>\n<p><em>\u201ci:guid=TOGUID(\u2018\u201d+Guid.toHexString(itemGuid)+\u201d\u2019)\u201d);<\/em> <\/div><\/section><\/p>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Poprawny przyk\u0142ad zastosowania parametr\u00f3w zapytania w OQL:<\/p>\n<p><em>ObjectIterator i=om.getObjectIterator(<\/em><\/p>\n<p><em>\u201cSELECT FROM com.cisag.app.general.obj.Item i WHERE \u201c+<\/em><\/p>\n<p><em>\u201ci:guid=?\u201d);<\/em><\/p>\n<p><em>i.setGuid(1,itemGuid);<\/em> <\/div><\/section>\n<h5 id=\"wykorzystanie-getobjectiterator\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_getObjectIterator\"><\/span>Wykorzystanie <em>getObjectIterator<\/em><span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"320\">Metoda <em data-start=\"7\" data-end=\"26\">getObjectIterator<\/em> selekcjonuje zbi\u00f3r instancji obiekt\u00f3w biznesowych danego obiektu biznesowego. Je\u017celi obiekt biznesowy ma ustawienie cache <em data-start=\"149\" data-end=\"154\">LRU<\/em> lub jest odczytywany z u\u017cyciem flag <em data-start=\"191\" data-end=\"204\">READ_UPDATE<\/em> albo <em data-start=\"210\" data-end=\"222\">READ_WRITE<\/em>, instrukcja SQL wygenerowana z OQL selekcjonuje atrybuty klucza podstawowego obiektu biznesowego.<\/p>\n<p data-start=\"0\" data-end=\"320\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Z zapytania OQL:<\/p>\n<p data-start=\"0\" data-end=\"320\"><em>SELECT FROM com.cisag.app.sales.obj.SalesOrder o<\/em><br \/>\n<em>WHERE o:number&gt;?<\/em><\/p>\n<p data-start=\"0\" data-end=\"320\">dla obiektu biznesowego przechowywanego w cache typu <em data-start=\"53\" data-end=\"58\">LRU<\/em> generowane jest nast\u0119puj\u0105ce zapytanie SQL:<\/p>\n<p data-start=\"0\" data-end=\"320\"><em>SELECT O.GUID FROM SALESORDER O WHERE O.NUMBER&gt;? <\/em><\/div><\/section><\/p>\n<p data-start=\"0\" data-end=\"320\">Na podstawie atrybut\u00f3w klucza podstawowego instancje obiekt\u00f3w biznesowych s\u0105 \u0142adowane metod\u0105 <em data-start=\"93\" data-end=\"109\">getObjectArray<\/em>.<br data-start=\"110\" data-end=\"113\" \/>Je\u017celi obiekt biznesowy nie jest odczytywany z cache lub jest odczytywany z u\u017cyciem flagi <em data-start=\"203\" data-end=\"217\">BYPASS_CACHE<\/em>, instrukcja SQL wygenerowana z OQL selekcjonuje wszystkie atrybuty obiektu biznesowego.<\/p>\n<p data-start=\"0\" data-end=\"320\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Z zapytania OQL:<\/p>\n<p data-start=\"0\" data-end=\"320\"><em>SELECT FROM com.cisag.app.sales.obj.SalesOrder o<\/em><br \/>\n<em>WHERE o:number&gt;?<\/em><\/p>\n<p data-start=\"0\" data-end=\"320\">dla obiektu biznesowego, kt\u00f3ry nie jest przechowywany w cache, generowane jest nast\u0119puj\u0105ce zapytanie SQL:<\/p>\n<p data-start=\"0\" data-end=\"320\"><em>SELECT * FROM SALESORDER O WHERE O.NUMBER&gt;?<\/em> <\/div><\/section><\/p>\n<p data-start=\"0\" data-end=\"395\">Selekcja atrybut\u00f3w klucza podstawowego jest przy <em data-start=\"49\" data-end=\"65\">cache hit rate<\/em> na poziomie oko\u0142o 70% szybsza ni\u017c selekcja wszystkich atrybut\u00f3w. Zazwyczaj jednak aplikacja nie jest w stanie jednoznacznie okre\u015bli\u0107, kt\u00f3ry spos\u00f3b dost\u0119pu jest korzystniejszy. W przypadku przetwarzania du\u017cych wolumen\u00f3w danych mo\u017ce by\u0107 jednak korzystne stosowanie flagi <em data-start=\"335\" data-end=\"349\">BYPASS_CACHE<\/em> r\u00f3wnie\u017c dla obiekt\u00f3w przechowywanych w cache.<\/p>\n<p data-start=\"397\" data-end=\"647\" data-is-last-node=\"\" data-is-only-node=\"\">Przy <em data-start=\"402\" data-end=\"418\">cache hit rate<\/em> r\u00f3wnym 0% selekcja przez klucz podstawowy jest wyra\u017anie wolniejsza ni\u017c selekcja pe\u0142nego obiektu. Natomiast przy <em data-start=\"531\" data-end=\"547\">cache hit rate<\/em> r\u00f3wnym 100% selekcja przez klucz podstawowy jest zdecydowanie szybsza ni\u017c selekcja pe\u0142nego obiektu.<\/p>\n<h5 data-start=\"397\" data-end=\"647\" id=\"wykorzystanie-getresultset\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_getResultSet\"><\/span>Wykorzystanie <em>getResultSet<\/em><span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"40\" data-end=\"161\">Metoda <em data-start=\"47\" data-end=\"61\">getResultSet<\/em> umo\u017cliwia \u2013 podobnie jak zapytanie SQL \u2013 selekcj\u0119 zbioru warto\u015bci z dowolnych obiekt\u00f3w biznesowych.<\/p>\n<p data-start=\"163\" data-end=\"454\">Je\u017celi z obiektu biznesowego potrzebnych jest jedynie stosunkowo niewiele atrybut\u00f3w, a <em data-start=\"250\" data-end=\"266\">cache hit rate<\/em> tego obiektu nie jest szczeg\u00f3lnie wysoki (&lt; 95%), bardziej op\u0142acalne mo\u017ce by\u0107 odczytanie atrybut\u00f3w za pomoc\u0105 <em data-start=\"376\" data-end=\"390\">getResultSet<\/em> ni\u017c budowanie pe\u0142nych obiekt\u00f3w przy u\u017cyciu <em data-start=\"434\" data-end=\"453\">getObjectIterator<\/em>.<\/p>\n<p data-start=\"163\" data-end=\"454\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Zapytanie OQL dla <em data-start=\"490\" data-end=\"509\">getObjectIterator<\/em><\/p>\n<p data-start=\"163\" data-end=\"454\"><em>SELECT FROM com.cisag.app.sales.obj.SalesOrder o<\/em><br \/>\n<em>WHERE o:number&gt;? <\/em><\/p>\n<p data-start=\"163\" data-end=\"454\">dzia\u0142a wolniej ni\u017c zapytanie OQL dla <em data-start=\"626\" data-end=\"640\">getResultSet<\/em><\/p>\n<p data-start=\"163\" data-end=\"454\"><em>SELECT o:guid, o:pickingStatus<\/em><br \/>\n<em>FROM com.cisag.app.sales.obj.SalesOrder o<\/em><br \/>\n<em>WHERE o:number&gt;?<\/em> <\/div><\/section><\/p>\n<h5 data-start=\"163\" data-end=\"454\" id=\"wykorzystanie-getupdatestatement\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_getUpdateStatement\"><\/span>Wykorzystanie <em>getUpdateStatement()<\/em><span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"968\" data-end=\"1228\">Metoda <em data-start=\"975\" data-end=\"997\">getUpdateStatement()<\/em> umo\u017cliwia wykonywanie instrukcji UPDATE oraz DELETE bezpo\u015brednio na bazie danych. Czas wykonania takich instrukcji jest zazwyczaj znacznie kr\u00f3tszy ni\u017c czas realizacji r\u00f3wnowa\u017cnej logiki opartej na instancjach obiekt\u00f3w biznesowych.<\/p>\n<p data-start=\"1230\" data-end=\"1450\">Po u\u017cyciu instrukcji aktualizacji wszystkie instancje danego obiektu biznesowego s\u0105 usuwane ze wszystkich cache wszystkich serwer\u00f3w aplikacyjnych w systemie. Zapewnia to sp\u00f3jno\u015b\u0107 <em data-start=\"1409\" data-end=\"1423\">shared cache<\/em> z zawarto\u015bci\u0105 bazy danych.<\/p>\n<p data-start=\"1452\" data-end=\"1659\">Cz\u0119ste stosowanie <em data-start=\"1470\" data-end=\"1492\">getUpdateStatement()<\/em> znacz\u0105co obni\u017ca efektywno\u015b\u0107 <em data-start=\"1521\" data-end=\"1535\">shared cache<\/em>. Z tego powodu instrukcje UPDATE powinny by\u0107 wykorzystywane g\u0142\u00f3wnie w reorganizacjach oraz w przetwarzaniu masowych danych.<\/p>\n<h5 data-start=\"1452\" data-end=\"1659\" id=\"przetwarzanie-blokowe-w-klasach-logiki\" ><span class=\"ez-toc-section\" id=\"Przetwarzanie_blokowe_w_klasach_logiki\"><\/span>Przetwarzanie blokowe w klasach logiki<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"144\">Ka\u017cdy etap przetwarzania musi operowa\u0107 na danych w jednostkach o odpowiedniej wielko\u015bci. Jednostki te nie mog\u0105 by\u0107 ani zbyt du\u017ce, ani zbyt ma\u0142e.<\/p>\n<p data-start=\"146\" data-end=\"321\">Je\u017celi przetwarzanie odbywa si\u0119 w zbyt du\u017cych jednostkach, zapotrzebowanie na zasoby (pami\u0119\u0107 operacyjn\u0105 oraz cz\u0119\u015bciowo CPU) po stronie serwera aplikacyjnego jest zbyt wysokie.<\/p>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u017celi logika \u0142aduje do pami\u0119ci operacyjnej wszystkie pozycje zam\u00f3wienia, jest to bardzo niekorzystne, poniewa\u017c liczba pozycji zam\u00f3wienia nie jest ograniczona. Niekt\u00f3rzy klienci u\u017cywaj\u0105 zam\u00f3wie\u0144 z mniej ni\u017c 10 pozycjami, inni mog\u0105 mie\u0107 zam\u00f3wienia licz\u0105ce nawet ponad 10 000 pozycji. Je\u017celi aplikacja za\u0142aduje 10 000 pozycji do pami\u0119ci operacyjnej, dana instancja aplikacji zu\u017cywa bardzo du\u017co pami\u0119ci i mo\u017ce doprowadzi\u0107 do jej przepe\u0142nienia, co skutkuje zako\u0144czeniem dzia\u0142ania serwera aplikacyjnego z powodu braku pami\u0119ci.<\/div><\/section>\n<p data-start=\"862\" data-end=\"1274\">Je\u017celi natomiast przetwarzanie odbywa si\u0119 w zbyt ma\u0142ych jednostkach, zapotrzebowanie na zasoby (obci\u0105\u017cenie bazy danych oraz cz\u0119\u015bciowo CPU) po stronie serwera aplikacyjnego r\u00f3wnie\u017c jest zbyt wysokie. Przy zbyt ma\u0142ych jednostkach dane s\u0105 zapisywane w zbyt ma\u0142ych transakcjach, co prowadzi do du\u017cego obci\u0105\u017cenia bazy danych. Dodatkowo w takim przypadku operacje odczytu zazwyczaj nie s\u0105 realizowane w spos\u00f3b blokowy.<\/p>\n<p data-start=\"1276\" data-end=\"1347\">Przy projektowaniu klas logiki nale\u017cy przestrzega\u0107 nast\u0119puj\u0105cych zasad:<\/p>\n<ul>\n<li data-start=\"1350\" data-end=\"1425\">jedna transakcja powinna obejmowa\u0107 maksymalnie 1000 obiekt\u00f3w biznesowych,<\/li>\n<li data-start=\"1428\" data-end=\"1518\">wszystkie operacje odczytu powinny by\u0107 realizowane blokowo za pomoc\u0105 <em data-start=\"1497\" data-end=\"1515\">getObjectArray()<\/em>,<\/li>\n<li data-start=\"1521\" data-end=\"1598\">logika powinna wykorzystywa\u0107 jedynie ograniczon\u0105 ilo\u015b\u0107 pami\u0119ci operacyjnej,<\/li>\n<li data-start=\"1601\" data-end=\"1658\">jedna instrukcja OQL nie powinna przekracza\u0107 4000 znak\u00f3w.<\/li>\n<\/ul>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Niepoprawny przyk\u0142ad przetwarzania blokowego:<\/p>\n<p><em>for (\u2026) {<\/em><br \/>\n<em>\u2026<\/em><br \/>\n<em>i=om.getObjectIterator(<\/em><br \/>\n<em>\u201cSELECT FROM com.cisag.app.sales.obj.SalesOrder so \u201c+<\/em><br \/>\n<em>\u201cWHERE so:status=? AND \u201d<\/em><br \/>\n<em>\u201cso:totalValue.grossValue.amount&gt;=? AND \u201c+<\/em><br \/>\n<em>\u201cso:totalValue.grossValue.amount&lt;?\u201d;<\/em><br \/>\n<em>i.setShort(1,x);<\/em><br \/>\n<em>i.setDecimal(2,y);<\/em><br \/>\n<em>i.setDecimal(3,z);<\/em><br \/>\n<em>\u2026<\/em><br \/>\n<em>}<\/em><\/p>\n<p data-start=\"0\" data-end=\"220\">W powy\u017cszym programie dla ka\u017cdego przebiegu p\u0119tli zewn\u0119trznej wykonywany jest dost\u0119p do tabeli <em data-start=\"95\" data-end=\"107\">SalesOrder<\/em>. Poniewa\u017c na atrybucie <em data-start=\"131\" data-end=\"161\">totalValue.grossValue.amount<\/em> nie istnieje indeks, dost\u0119p ten jest relatywnie kosztowny.<\/p>\n<p data-start=\"222\" data-end=\"261\" data-is-last-node=\"\" data-is-only-node=\"\">Poprawny przyk\u0142ad przetwarzania blokowego:<\/p>\n<p data-start=\"222\" data-end=\"261\" data-is-last-node=\"\" data-is-only-node=\"\"><em>StringBuffer oql = new StringBuffer(\u201cSELECT \u201c+<\/em><br \/>\n<em>\u201dFROM com.cisag.app.sales.obj.SalesOrder so<\/em><br \/>\n<em>\u201cWHERE so:status=? AND (\u201c);<\/em><br \/>\n<em>ArrayList values = new ArrayList();<\/em><br \/>\n<em>String separator = \u201c\u201d;<\/em><br \/>\n<em>for (\u2026) {<\/em><br \/>\n<em>\u2026<\/em><br \/>\n<em>oql.append(separator);<\/em><br \/>\n<em>oql.append(\u201c(so:totalValue.grossValue.amount&gt;=? AND \u201c+<\/em><br \/>\n<em>\u201cso:totalValue.grossValue.amount&lt;?)\u201d<\/em><br \/>\n<em>values.add(x);<\/em><br \/>\n<em>values.add(y);<\/em><br \/>\n<em>values.add(z);<\/em><br \/>\n<em>separator=\u201d OR \u201c;<\/em><\/p>\n<p data-start=\"222\" data-end=\"261\" data-is-last-node=\"\" data-is-only-node=\"\"><em>if (blockSize&gt;10 || \u2026) {<\/em><br \/>\n<em>oql.append(\u201c)\u201d);<\/em><br \/>\n<em>i=om.getObjectIterator(oql.toString());<\/em><br \/>\n<em>int idx=1;<\/em><br \/>\n<em>for (Iterator v=values.iterator(); v.hasNext();) {<\/em><br \/>\n<em>i.setShort(idx++,((Short)v.next()).shortValue());<\/em><br \/>\n<em>i.setDecimal(idx++,(CisDecimal)v.next());<\/em><br \/>\n<em>i.setDecimal(idx++,(CisDecimal)v.next());<\/em><br \/>\n<em>}<\/em><br \/>\n<em>\u2026<\/em><br \/>\n<em>separator = \u201c\u201d;<\/em><br \/>\n<em>oql = new StringBuffer(\u201cSELECT \u201c+<\/em><br \/>\n<em>\u201dFROM com.cisag.app.sales.obj.SalesOrder so<\/em><br \/>\n<em>\u201cWHERE so:status=? AND (\u201c);<\/em><br \/>\n<em>\u2026<\/em><br \/>\n<em>} <\/em><\/p>\n<p data-start=\"222\" data-end=\"261\" data-is-last-node=\"\" data-is-only-node=\"\">W powy\u017cszym programie dost\u0119p do tabeli <em data-start=\"39\" data-end=\"51\">SalesOrder<\/em> wykonywany jest tylko co dziesi\u0105ty przebieg p\u0119tli zewn\u0119trznej. Dzi\u0119ki temu obci\u0105\u017cenie bazy danych zostaje w przybli\u017ceniu zmniejszone dziesi\u0119ciokrotnie.<\/div><\/section>\n<h5 data-start=\"222\" data-end=\"261\" id=\"wyszukiwanie-instrukcji-bazodanowych-w-aplikacjach\" ><span class=\"ez-toc-section\" id=\"Wyszukiwanie_instrukcji_bazodanowych_w_aplikacjach\"><\/span>Wyszukiwanie instrukcji bazodanowych w aplikacjach<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"61\" data-end=\"312\">Je\u017celi na podstawie monitor\u00f3w wydajno\u015bci lub protoko\u0142\u00f3w profilowania zidentyfikowano jedn\u0105 lub kilka instrukcji bazodanowych odpowiedzialnych za zbyt d\u0142ugi czas odpowiedzi aplikacji, nale\u017cy znale\u017a\u0107 metody klas, kt\u00f3re wykonuj\u0105 te instrukcje bazodanowe:<\/p>\n<ol>\n<li data-start=\"317\" data-end=\"367\">Uruchomienie serwera aplikacyjnego w debuggerze.<\/li>\n<li data-start=\"371\" data-end=\"414\">Zalogowanie si\u0119 do serwera aplikacji.<\/li>\n<li data-start=\"418\" data-end=\"524\">Przygotowanie \u015brodowiska w taki spos\u00f3b, aby mo\u017cliwe by\u0142o uruchomienie problematycznej funkcji aplikacji.<\/li>\n<li data-start=\"528\" data-end=\"621\">Ustawienie w debuggerze breakpointu w aplikacji na pierwszej linii problematycznej funkcji.<\/li>\n<li data-start=\"625\" data-end=\"764\">W\u0142\u0105czenie wyprowadzania wszystkich wykonywanych instrukcji bazodanowych:<br data-start=\"697\" data-end=\"700\" \/><em>dbgcls -class:com.cisag.sys.kernel.sql.CisPreparedStatement<\/em>.<\/li>\n<li data-start=\"768\" data-end=\"807\">Uruchomienie problematycznej funkcji.<\/li>\n<li data-start=\"811\" data-end=\"914\">Debugowanie do momentu, a\u017c poszukiwana instrukcja bazodanowa zostanie wy\u015bwietlona jako komunikat <em>debug<\/em>.<\/li>\n<\/ol>\n<p data-start=\"916\" data-end=\"1121\">Przy d\u0142ugich czasach wykonania nale\u017cy zoptymalizowa\u0107 instrukcj\u0119 bazodanow\u0105, natomiast przy bardzo cz\u0119stym wykonywaniu instrukcji o kr\u00f3tkim czasie wykonania nale\u017cy ograniczy\u0107 cz\u0119stotliwo\u015b\u0107 jej uruchamiania.<\/p>\n<h4 data-start=\"916\" data-end=\"1121\" id=\"wyszukiwania-i-listy\" ><span class=\"ez-toc-section\" id=\"Wyszukiwania_i_listy\"><\/span>Wyszukiwania i listy<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"916\" data-end=\"1121\">W wyszukiwaniach i listach najcz\u0119\u015bciej generowane s\u0105 z\u0142o\u017cone zapytania bazodanowe. Zapytania te s\u0105 dynamicznie sk\u0142adane w zale\u017cno\u015bci od u\u017cytych parametr\u00f3w wyszukiwania. Ka\u017cdy system mo\u017ce \u2013 w zale\u017cno\u015bci od wykorzystywanej funkcjonalno\u015bci \u2013 generowa\u0107 inne zapytania. Z tego powodu, szczeg\u00f3lnie w przypadku list, nie zawsze jest \u0142atwo dostarczy\u0107 w standardzie indeksy, kt\u00f3re by\u0142yby u\u017cyteczne dla wszystkich mo\u017cliwych wymaga\u0144 klient\u00f3w.<\/p>\n<h5 data-start=\"916\" data-end=\"1121\" id=\"wybor-wartosci-domyslnych-dla-pol-wyszukiwania\" ><span class=\"ez-toc-section\" id=\"Wybor_wartosci_domyslnych_dla_pol_wyszukiwania\"><\/span>Wyb\u00f3r warto\u015bci domy\u015blnych dla p\u00f3l wyszukiwania<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"265\">W wyszukiwaniach i aplikacjach typu listy, w kt\u00f3rych wy\u015bwietlane s\u0105 wyniki wyszukiwania, s\u0105 zawsze sortowane. Sortowanie du\u017cych zbior\u00f3w wynik\u00f3w jest bardzo czasoch\u0142onne. Tylko rzadko istnieje mo\u017cliwo\u015b\u0107 utworzenia sensownego indeksu na potrzeby sortowania w wyszukiwaniach.<\/p>\n<p data-start=\"267\" data-end=\"623\">Wielu u\u017cytkownik\u00f3w otwiera wyszukiwanie i uruchamia je bez zaw\u0119\u017cania wynik\u00f3w przy u\u017cyciu kryteri\u00f3w wyszukiwania. Je\u017celi warto\u015bci domy\u015blne wyszukiwania nie zaw\u0119\u017caj\u0105 wynik\u00f3w, wybierany jest ca\u0142y zas\u00f3b danych i prawdopodobnie musi on zosta\u0107 jeszcze posortowany. Powoduje to na przyk\u0142ad w przypadku danych ruchowych ekstremalnie wysokie obci\u0105\u017cenie bazy danych.<\/p>\n<p data-start=\"625\" data-end=\"831\">Je\u017celi warto\u015bci domy\u015blne p\u00f3l wyszukiwania zostan\u0105 dobrane w taki spos\u00f3b, aby zbi\u00f3r wynik\u00f3w mia\u0142 ograniczony rozmiar, uruchamianie wyszukiwania z warto\u015bciami domy\u015blnymi nie b\u0119dzie tak mocno obci\u0105\u017ca\u0107 systemu.<\/p>\n<p data-start=\"833\" data-end=\"1317\">W szczeg\u00f3lno\u015bci dane ruchowe cz\u0119sto dziel\u0105 si\u0119 na dane aktywne i historyczne. Przyk\u0142adowo wszystkie zam\u00f3wienia o statusie innym ni\u017c zrealizowany nale\u017c\u0105 do danych aktywnych, natomiast wszystkie zam\u00f3wienia zrealizowane stanowi\u0105 raczej dane historyczne. Wolumen danych aktywnych jest wyra\u017anie mniejszy ni\u017c wolumen danych historycznych. Pola wyszukiwania w wyszukiwaniach i listach powinny by\u0107 zawsze wst\u0119pnie ustawione w taki spos\u00f3b, aby wyszukiwanie obejmowa\u0142o wy\u0142\u0105cznie dane aktywne.<\/p>\n<h5 data-start=\"833\" data-end=\"1317\" id=\"dostosowanie-specyficzne-dla-klienta\" ><span class=\"ez-toc-section\" id=\"Dostosowanie_specyficzne_dla_klienta\"><\/span>Dostosowanie specyficzne dla klienta<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p data-start=\"0\" data-end=\"354\">Wyszukiwania, a w szczeg\u00f3lno\u015bci listy, mog\u0105 zosta\u0107 w przypadku problem\u00f3w wydajno\u015bciowych dostosowane do potrzeb klienta. W takim przypadku nale\u017cy ukry\u0107 wszystkie pola wyszukiwania i sortowania, kt\u00f3rych klient nie potrzebuje. Im mniej dost\u0119pnych jest mo\u017cliwo\u015bci wyszukiwania i sortowania, tym \u0142atwiej jest tworzy\u0107 indeksy specyficzne dla danego klienta.<\/p>\n<p data-start=\"356\" data-end=\"545\">Je\u017celi istnieje bardzo wiele mo\u017cliwo\u015bci wyszukiwania i sortowania oraz nie zostan\u0105 one ograniczone, mog\u0105 wyst\u0105pi\u0107 kombinacje, kt\u00f3re charakteryzuj\u0105 si\u0119 bardzo niekorzystnym czasem wykonania.<\/p>\n<h5 data-start=\"356\" data-end=\"545\" id=\"wykorzystanie-fragmentow\" ><span class=\"ez-toc-section\" id=\"Wykorzystanie_fragmentow\"><\/span>Wykorzystanie fragment\u00f3w<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<div class=\"text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] @w-sm\/main:[--thread-content-margin:--spacing(6)] @w-lg\/main:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:40rem] @w-lg\/main:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group\/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\" tabindex=\"-1\">\n<div class=\"flex max-w-full flex-col grow\">\n<div class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&amp;]:mt-1\" dir=\"auto\" data-message-author-role=\"assistant\" data-message-id=\"814d5175-e9b0-42c5-90f8-3798a9aa5979\" data-message-model-slug=\"gpt-5-2\">\n<div class=\"flex w-full flex-col gap-1 empty:hidden first:pt-[1px]\">\n<div class=\"markdown prose dark:prose-invert w-full break-words dark markdown-new-styling\">\n<p data-start=\"0\" data-end=\"324\">Nale\u017cy podzieli\u0107 wykorzystywane wyszukiwanie OQL na jak najwi\u0119ksz\u0105 liczb\u0119 fragment\u00f3w. Dzi\u0119ki fragmentom wynikowe zapytanie SQL mo\u017ce by\u0107 dynamicznie rozszerzane w zale\u017cno\u015bci od wymaga\u0144. Im drobniej zdefiniowane s\u0105 fragmenty, tym lepiej zapytanie mo\u017ce zosta\u0107 dopasowane i tym mniejsze obci\u0105\u017cenie jest generowane po stronie bazy danych.<\/p>\n<h4 data-start=\"0\" data-end=\"324\" id=\"aplikacje-interaktywne\" ><span class=\"ez-toc-section\" id=\"Aplikacje_interaktywne\"><\/span>Aplikacje interaktywne<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p data-start=\"0\" data-end=\"324\">W aplikacjach interaktywnych u\u017cytkownik oczekuje kr\u00f3tkich czas\u00f3w odpowiedzi na swoje dzia\u0142ania. Akceptowalny czas odpowiedzi zale\u017cy od funkcji, z kt\u00f3rej u\u017cytkownik korzysta. Przyk\u0142adowo przy \u0142adowaniu i zapisywaniu rozbudowanych obiekt\u00f3w u\u017cytkownik akceptuje czasy odpowiedzi w przedziale od 0,5 do 5 sekund. Natomiast podczas edycji zam\u00f3wienia dodanie nowej pozycji powinno nast\u0105pi\u0107 w czasie kr\u00f3tszym ni\u017c 0,5 sekundy, aby nie by\u0142o odbierane przez u\u017cytkownika jako uci\u0105\u017cliwe.<\/p>\n<p data-start=\"0\" data-end=\"324\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-41938 size-full\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_5.png\" alt=\"\" width=\"321\" height=\"369\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_5.png 321w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_5-261x300.png 261w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2026\/01\/Optymalizacja_5-43x50.png 43w\" sizes=\"auto, (max-width: 321px) 100vw, 321px\" \/><\/p>\n<p style=\"text-align: center;\" data-start=\"0\" data-end=\"324\"><em>Przyk\u0142adowy przebieg round-tripu<\/em><\/p>\n<p data-start=\"36\" data-end=\"117\">Odczuwalny dla u\u017cytkownika czas round-tripu sk\u0142ada si\u0119 z nast\u0119puj\u0105cych element\u00f3w:<\/p>\n<ul>\n<li data-start=\"120\" data-end=\"164\">czasu budowy ekranu w Internet Explorerze,<\/li>\n<li data-start=\"167\" data-end=\"193\">czasu transmisji danych,<\/li>\n<li data-start=\"196\" data-end=\"217\">czasu oblicze\u0144 GUI,<\/li>\n<li data-start=\"220\" data-end=\"255\">czasu wykonania logiki aplikacji,<\/li>\n<li data-start=\"258\" data-end=\"287\">czasu dost\u0119pu do bazy danych.<\/li>\n<\/ul>\n<p data-start=\"289\" data-end=\"575\">GUI (\u0142\u0105cznie z transmisj\u0105 danych i budow\u0105 ekranu w Internet Explorerze) stanowi \u2013 szczeg\u00f3lnie przy kr\u00f3tkich round-tripach (poni\u017cej 1 s) \u2013 relatywnie wysoki procent ca\u0142kowitego czasu. Poniewa\u017c udzia\u0142 ten w du\u017cym stopniu zale\u017cy od konkretnego przypadku u\u017cycia, pomiary s\u0105 tutaj niezb\u0119dne.<\/p>\n<p data-start=\"289\" data-end=\"575\"><section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u017celi round-trip nie powinien przekracza\u0107 500 ms, a GUI zu\u017cywa 200 ms, na logik\u0119 aplikacji pozostaje jedynie 300 ms.<\/p>\n<p data-start=\"289\" data-end=\"575\">Je\u017celi pojedynczy dost\u0119p do bazy danych trwa \u015brednio 10 ms, w takim round-tripie mo\u017ce wyst\u0105pi\u0107 maksymalnie 30 dost\u0119p\u00f3w do bazy danych.<\/div><\/section><\/p>\n<p data-start=\"849\" data-end=\"1509\">Liczba dost\u0119p\u00f3w do bazy danych jest zazwyczaj kluczowym czynnikiem wp\u0142ywaj\u0105cym na czas zu\u017cywany przez logik\u0119 aplikacji. W jednym round-tripie w \u017cadnym wypadku nie powinno wyst\u0119powa\u0107 wi\u0119cej ni\u017c 50 dost\u0119p\u00f3w do bazy danych. Liczba dost\u0119p\u00f3w do bazy danych na round-trip jest mierzona za pomoc\u0105 standardowego monitora wydajno\u015bci bazy danych. Mo\u017cna j\u0105 wy\u015bwietli\u0107 przy u\u017cyciu raportu <em data-start=\"1226\" data-end=\"1270\">Czasoch\u0142onne akcje posortowane wed\u0142ug sumy<\/em>. Je\u017celi w cz\u0119sto wykorzystywanej operacji wyst\u0119puje wi\u0119cej ni\u017c 50 dost\u0119p\u00f3w do bazy danych, operacja ta musi zosta\u0107 zoptymalizowana. Oczywi\u015bcie istotna jest nie tylko liczba, ale r\u00f3wnie\u017c czas trwania poszczeg\u00f3lnych dost\u0119p\u00f3w do bazy danych.<\/p>\n<p data-start=\"1511\" data-end=\"2043\">Za pomoc\u0105 monitor\u00f3w wydajno\u015bci lub poprzez wy\u015bwietlanie zapyta\u0144 bazodanowych o d\u0142ugim czasie wykonania mo\u017cna zidentyfikowa\u0107 zapytania bazodanowe o du\u017cej czasoch\u0142onno\u015bci. W aplikacjach dialogowych nale\u017cy bezwzgl\u0119dnie unika\u0107 z\u0142o\u017conych zapyta\u0144 bazodanowych. Dlatego ka\u017cdorazowo nale\u017cy sprawdzi\u0107 plan dost\u0119pu dla ka\u017cdego zapytania bazodanowego, kt\u00f3rego wykonanie trwa d\u0142u\u017cej ni\u017c 100 ms. <em data-start=\"1894\" data-end=\"1911\">Full table scan<\/em> w aplikacjach dialogowych prowadzi, wraz ze wzrostem ilo\u015bci danych w systemie produkcyjnym, do nieakceptowalnych czas\u00f3w odpowiedzi.<\/p>\n<p data-start=\"2045\" data-end=\"2332\" data-is-last-node=\"\" data-is-only-node=\"\">W przypadku funkcji interaktywnych nale\u017cy \u2013 niezale\u017cnie od wielko\u015bci danych \u2013 zna\u0107 g\u00f3rn\u0105 granic\u0119 maksymalnego czasu wykonania. Je\u017celi nie jest mo\u017cliwe jej okre\u015blenie, na przyk\u0142ad dlatego, \u017ce czas zale\u017cy od ilo\u015bci przetwarzanych danych, funkcj\u0119 t\u0119 nale\u017cy realizowa\u0107 w przetwarzaniu w tle.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":27,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"footnotes":""},"class_list":["post-9258","ht_kb","type-ht_kb","status-publish","format-standard","hentry","ht_kb_category-persistence-service"],"_links":{"self":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/9258","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb"}],"about":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/types\/ht_kb"}],"author":[{"embeddable":true,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/comments?post=9258"}],"version-history":[{"count":64,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/9258\/revisions"}],"predecessor-version":[{"id":41951,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/9258\/revisions\/41951"}],"wp:attachment":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/media?parent=9258"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}