<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: yes -->
<sect1 id="zend.db.profiler" xmlns:xi="http://www.w3.org/2001/XInclude">

    <title>Zend_Db_Profiler</title>

    <sect2 id="zend.db.profiler.introduction">

        <title>Wprowadzenie</title>

        <para>
            <code>Zend_Db_Profiler</code> może być włączony aby pozwolić na
            profilowanie zapytań. Profilowanie umożliwia zbadanie czasu trwania
            zapytań pozwalając na inspekcję przeprowadzonych zapytań bez potrzeby
            dodawania nadmiarowego kodu do klas. Zaawansowane użycie pozwala także
            programiście decydować o tym, jakich typów zapytania mają być profilowane.
        </para>

        <para>
            Włącz profiler przekazując odpowiednią dyrektywę do konstruktora
            adaptera lub wywołując później metodę adaptera.
        </para>

        <programlisting role="php"><![CDATA[
$params = array (
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test',
    'profiler' => true  // włącz profiler; ustaw false aby wyłączyć (domyślne wyłączony)
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

// wyłącz profiler:
$db->getProfiler()->setEnabled(false);

// włącz profiler:
$db->getProfiler()->setEnabled(true);
]]>
        </programlisting>

        <para>
            Wartość opcji '<code>profiler</code>' jest dość elastyczna. Jest
            ona interpretowana zależnie id jej typu. W większości przypadków
            powinieneś użyć wartości logicznej, ale inne typy pozwalają na
            dostosowanie zachowania profilera do własnych potrzeb.
        </para>

        <para>
            Parametr logiczny włącza profiler jeśli ma wartość
            <code>TRUE</code> lub wyłącza jeśli ma wartość <code>FALSE</code>.
            Klasą profilera domyślnie jest klasa <code>Zend_Db_Profiler</code>.
            <programlisting role="php"><![CDATA[
$params['profiler'] = true;
$db = Zend_Db::factory('PDO_MYSQL', $params);
]]>
            </programlisting>
        </para>

        <para>
            Przekazanie instancji obiektu profilera powoduje jej użycie przez
            adapter bazy danych. Musi to być obiekt klasy
            <code>Zend_Db_Profiler</code> lub klasy ją rozszerzającej. Aktywacja
            profilera odbywa się osobno.
            <programlisting role="php"><![CDATA[
$profiler = MyProject_Db_Profiler();
$profiler->setEnabled(true);
$params['profiler'] = $profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
]]>
            </programlisting>
        </para>

        <para>
            Argument może być tablicą asocjacyjną zawierającą wszystkie lub
            jeden z kluczy '<code>enabled</code>', '<code>instance</code>', oraz
            '<code>class</code>'. Klucz '<code>enabled</code>' odpowiada wartości
            logicznej, a '<code>instance</code>' wartości instancji, obie są
            opisane powyżej. Klucz '<code>class</code>' jest używany do podania
            nazwy klasy jaka ma być użyta we własnym profilerze. Musi być to
            obiekt klasy <code>Zend_Db_Profiler</code> lub klasy ją rozszerzającej.
            Instancja klasy jest tworzona bez żadnych argumentów. Opcja
            '<code>class</code>' jest ingorowana jeśli podana jest opcja
            '<code>instance</code>'.
            <programlisting role="php"><![CDATA[
$params['profiler'] = array(
    'enabled' => true,
    'class'   => 'MyProject_Db_Profiler'
);
$db = Zend_Db::factory('PDO_MYSQL', $params);
]]>
            </programlisting>
        </para>

        <para>
            Ostatecznie, argument może być obiektem klasy <code>Zend_Config</code>
            zawierającym właściwości, które są traktowane jako klucze tablicy
            opisane powyżej. Przykładowo plik "config.ini" może zawierać
            następujące dane:
            <programlisting role="ini"><![CDATA[
[main]
db.profiler.class   = "MyProject_Db_Profiler"
db.profiler.enabled = true
]]>
            </programlisting>

            Konfiguracja może być przekazana za pomocą takiego kodu PHP:

            <programlisting role="php"><![CDATA[
$config = new Zend_Config_Ini('config.ini', 'main');
$params['profiler'] = $config->db->profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
]]>
            </programlisting>

            Właściwość '<code>instance</code>' może być użyta w następujący sposób:
            <programlisting role="php"><![CDATA[
$profiler = new MyProject_Db_Profiler();
$profiler->setEnabled(true);
$configData = array(
    'instance' => $profiler
);
$config = new Zend_Config($configData);
$params['profiler'] = $config;
$db = Zend_Db::factory('PDO_MYSQL', $params);
]]>
            </programlisting>

        </para>

    </sect2>

    <sect2 id="zend.db.profiler.using">

        <title>Użycie profilera</title>

        <para>
            W dowolnym momencie możesz pobrać profiler używając metody
            adaptera <code>getProfiler()</code>:
        </para>

        <programlisting role="php"><![CDATA[
$profiler = $db->getProfiler();
]]>
        </programlisting>

        <para>
            Zwraca to instancję <code>Zend_Db_Profiler</code>. Używając tej
            instancji programista może zbadać zapytania używając rozmaitych
            metod:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <code>getTotalNumQueries()</code> zwraca liczbę wszystkich
                    zapytań które były profilowane.
                </para>
            </listitem>
            <listitem>
                <para>
                    <code>getTotalElapsedSecs()</code> zwraca całkowity czas
                    trwania profilowanych zapytań.
                </para>
            </listitem>
            <listitem>
                <para>
                    <code>getQueryProfiles()</code> zwraca tablicę wszystkich
                    profilów zapytań.
                </para>
            </listitem>
            <listitem>
                <para>
                    <code>getLastQueryProfile()</code> zwraca ostatni (najnowszy)
                    profil zapytania, niezależnie od tego czy zostało ono zakończone czy
                    nie (jeśli nie zostało, to czas zakończenia będzie miał wartość <constant>NULL</constant>)
                </para>
            </listitem>
            <listitem>
                <para>
                    <code>clear()</code> czyści wszystkie poprzednie profile
                    zapytań ze stosu.
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Wartość zwracana przez <code>getLastQueryProfile()</code> oraz
            pojedyncze elementy tablicy zwracanej przez <code>getQueryProfiles()</code>
            są obiektami <code>Zend_Db_Profiler_Query</code>, które dają możliwość
            sprawdzenia osobno każdego zapytania.
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    Metoda <code>getQuery()</code> zwraca tekst SQL zapytania.
                    Tekst przygotowanego zapytania SQL z parametrami jest
                    tekstem w takiej postaci w jakiej był on przygotowany, więc
                    zawiera on etykiety, a nie wartości użyte podczas wykonania
                    zapytania.
                </para>
            </listitem>
            <listitem>
                <para>
                    Metoda <code>getQueryParams()</code> zwraca tablicę wartości
                    parametrów użytych podczas wykonania przygotowanego
                    zapytania. Odnosi się to do parametrów oraz do argumentów
                    metody <code>execute()</code>. Klucze tablicy są oparte na
                    pozycji (od 1 w górę) lub nazwane (łańcuchy znaków).
                </para>
            </listitem>
            <listitem>
                <para>
                    Metoda <code>getElapsedSecs()</code> zwraca czas trwania zapytania
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Informacja której dostarcza <code>Zend_Db_Profiler</code> jest
            użyteczna przy profilowaniu wąskich gardeł w aplikacjach oraz
            do szukania błędów w wykonanych zapytaniach. Na przykład aby
            zobaczyć ostatnie zapytanie jakie było wykonane:
        </para>

        <programlisting role="php"><![CDATA[
$query = $profiler->getLastQueryProfile();

echo $query->getQuery();
]]>
        </programlisting>

        <para>
            Możliwe, że strona generuje się powoli; użyj profilera aby ustalić
            czas wykonania wszystkich zapytań, a następnie przejść poprzez
            zapytania aby znaleść te, które trwało najdłużej:
        </para>

        <programlisting role="php"><![CDATA[
$totalTime    = $profiler->getTotalElapsedSecs();
$queryCount   = $profiler->getTotalNumQueries();
$longestTime  = 0;
$longestQuery = null;

foreach ($profiler->getQueryProfiles() as $query) {
    if ($query->getElapsedSecs() > $longestTime) {
        $longestTime  = $query->getElapsedSecs();
        $longestQuery = $query->getQuery();
    }
}

echo 'Wykonano ' . $queryCount . ' zapytań w czasie ' . $totalTime . ' sekund' . "\n";
echo 'Średni czas trwania zapytania: ' . $totalTime / $queryCount . ' sekund' . "\n";
echo 'Zapytań na sekundę:: ' . $queryCount / $totalTime . "\n";
echo 'Czas trwania najdłuższego zapytania: ' . $longestTime . "\n";
echo "Najdłuższe zapytanie: \n" . $longestQuery . "\n";
]]>
        </programlisting>

    </sect2>

    <sect2 id="zend.db.profiler.advanced">

        <title>Zaawansowane użycie profilera</title>

        <para>
            Oprócz sprawdzania zapytań, profiler pozwala także programiście na
            określenie typów zapytań które mają być profilowane. Poniższe
            metody operują na instancji <code>Zend_Db_Profiler</code>:
        </para>

        <sect3 id="zend.db.profiler.advanced.filtertime">
            <title>Filtrowanie ze względu na czas trwania zapytania</title>

            <para>
                <code>setFilterElapsedSecs()</code> pozwala programiście ustalić
                minimalny czas trwania zapytania jaki jest potrzebny do tego by
                zostało ono profilowane. Aby usunąć filtr, wywołaj metodę z
                wartością null w parametrze.
            </para>

            <programlisting role="php"><![CDATA[
// Profiluj tylko zapytania które trwają przynajmniej 5 sekund:
$profiler->setFilterElapsedSecs(5);

// Profiluj wszystkie zapytania, niezależnie od czasu ich trwania:
$profiler->setFilterElapsedSecs(null);
]]>
            </programlisting>
        </sect3>

        <sect3 id="zend.db.profiler.advanced.filtertype">
            <title>Filtrowanie ze względu na typ zapytania</title>

            <para>
                <code>setFilterQueryType()</code> pozwala programiście określić,
                które typy zapytań powinny być profilowane; aby profilować
                zapytania wielu typów użyj logicznego operatora OR. Typy zapytań
                są zdefiniowane jako stałe w <code>Zend_Db_Profiler</code>:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::CONNECT</code>: operacje
                        połączenia lub wybierania bazy danych.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::QUERY</code>: ogólne zapytania
                         które nie pasują do pozostałych typów.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::INSERT</code>: każde zapytanie
                        które wstawia nowe dane do bazy, generalnie SQL INSERT.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::UPDATE</code>: każde zapytanie
                        ktore uaktualnia dane w bazie, najczęściej SQL UPDATE.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::DELETE</code>: każde zapytanie
                        które usuwa istnięjące dane, najczęściej SQL DELETE.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::SELECT</code>: każde zapytanie
                        które pobiera istnięjące dane, najczęściej SQL SELECT.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <code>Zend_Db_Profiler::TRANSACTION</code>: każda
                        operacja transakcyjna, taka jak start transakcji, potwierdzenie
                        zmian czy ich cofnięcie.
                    </para>
                </listitem>
            </itemizedlist>

            <para>
                Analogicznie jak w metodzie <code>setFilterElapsedSecs()</code>,
                możesz usunąć wszystkie istniejące filtry przekazując metodzie
                pusty parametr <code>null</code>.
            </para>

            <programlisting role="php"><![CDATA[
// profiluj tylko zapytania SELECT
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);

// profiluj zapytania SELECT, INSERT, oraz UPDATE
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

// profiluj zapytania DELETE
$profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);

// Usuń wszystkie filtry
$profiler->setFilterQueryType(null);
]]>
            </programlisting>

        </sect3>

        <sect3 id="zend.db.profiler.advanced.getbytype">
            <title>Pobieranie profili na podstawie typów zapytań</title>

            <para>
                Użycie metody <code>setFilterQueryType()</code> może zmniejszyć
                ilość wygenerowanych profili. Jakkolwiek, czasem bardziej użyteczne
                jest przechowywanie wszystkich profili i wyświetlanie tylko
                tych których potrzebujesz w danym momencie. Inną funkcjonalnością
                metody <code>getQueryProfiles()</code> jest to, że może ona
                przeprowadzić te filtrowanie w locie, po przekazaniu typu
                zapytań (lub logicznej kombinacji typów zapytań) jako pierwszego
                argumentu; przejdź do <xref linkend="zend.db.profiler.advanced.filtertype" />
                aby zobaczyć listę stałych określających typy zapytań.
            </para>

            <programlisting role="php"><![CDATA[
// Pobierz jedynie profile zapytań SELECT
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);

// Pobierz jedynie profile zapytań SELECT, INSERT, oraz UPDATE
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

// Pobierz jedynie profile zapytań DELETE
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
]]>
            </programlisting>

        </sect3>

    </sect2>

    <sect2 id="zend.db.profiler.profilers">
        <title>Wyspecjalizowane profilery</title>

        <para>
            Wyspecjalizowany profiler jest obiektem klasy dziedziczącej po
            klasie <code>Zend_Db_Profiler</code>. Wyspecjalizowane profilery
            traktują profilowane informacje w szczególny sposób.
        </para>

        <xi:include href="Zend_Db_Profiler-Firebug.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Db_Profiler-Firebug.xml" /></xi:fallback>
        </xi:include>

    </sect2>

</sect1>
