6.2. Zend_Db_Profiler
Пред. | Глава 6. Zend_Db | След.

## 6.2. Zend_Db_Profiler

### 6.2.1. Введение

`Zend_Db_Profiler` может быть включен для для того, чтобы сделать возможным профайлинг запросов. Профaйлы включают в себя запросы, обработанные адаптером, а также время, затраченное на обработку запроса. Это позволяет исследовать выполненные запросы без добавления дополнительного отладочного кода в классы. Расширенное использование также позволяет разработчикам указывать, для каких запросов создавать профайлы.

Включение профайлера производится либо передачей директивы конструктору адаптера, либо более поздним обращением к адаптеру для включения.

    <?php
    require_once 'Zend/Db.php';

    $params = array (
        'host'     => '127.0.0.1',
        'username' => 'malory',
        'password' => '******',
        'dbname'   => 'camelot',
        'profiler' => true  // включение профайлера;
                            // для отключения используется false (значение по умолчанию)
    );

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

    // отключение профайлера:
    $db->getProfiler()->setEnabled(false);

    // включение профайлера:
    $db->getProfiler()->setEnabled(true);
    ?>

### 6.2.2. Использование профайлера

Получение профайлера производится в любой момент с помощью метода `getProfiler()` в адаптере БД:

    <?php
    $profiler = $db->getProfiler();
    ?>

Это вернет экземпляр класса `Zend_Db_Profiler`. С помощью этого экземпляра разработчик может изучать запросы, используя различные методы:

- `getTotalNumQueries()` возвращает общее количество запросов, которые были обработаны профайлером.
- `getTotalElapsedSecs()` возвращает общее количество секунд, затраченное на все запросы, обработанные профайлером.
- `getQueryProfiles()` возвращает массив всех профайлов запросов.
- `getLastQueryProfile()` возвращает последний (самый недавний) профайл запроса, безотносительно того, был ли запрос завершен (Если не был завершен, то конечное время будет равно `NULL`).
- `clear()` удаляет все профайлы прошлых запросов из стека.

Возвращаемое `getLastQueryProfile()` значение и отдельные элементы `getQueryProfiles()` являются объектами `Zend_Db_Profiler_Query`, которые дают возможность исследовать отдельные запросы:

- `getQuery()` возвращает код SQL-запроса.
- `getElapsedSecs()` возвращает время выполнения запроса в секундах.

Информация, предоставляемая `Zend_Db_Profiler`, полезна для выявления "узких мест" в приложениях и отладки запросов. Например, чтобы посмотреть, какой запрос выполнялся последним:

    <?php
    $query = $profiler->getLastQueryProfile();

    echo $query->getQuery();
    ?>

Возможно, страница генерируется медленно. Используйте профайлер для того, чтобя сначала определить общее количество секунд для всех запросов, затем выполните обход всех запросов, чтобы найти тот, который выполняется дольше всех:

    <?php
    $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 'Executed ' . $queryCount . ' queries in ' . $totalTime . ' seconds' . "\n";
    echo 'Average query length: ' . $totalTime / $queryCount . ' seconds' . "\n";
    echo 'Queries per second: ' . $queryCount / $totalTime . "\n";
    echo 'Longest query length: ' . $longestTime . "\n";
    echo "Longest query: \n" . $longestQuery . "\n";
    ?>

### 6.2.3. Расширенное использование профайлера

Кроме исследования запросов, профайлер также дает возможность разработчику фильтровать запросы, для которых создаются профайлы. Следующие методы работают на экземпляре `Zend_Db_Profiler`:

#### 6.2.3.1. Фильтрация по времени выполнения запроса

`setFilterElapsedSecs()` дает возможность разработчику устанавливать минимальное время запроса, после которого будет проводиться профайлиг запросов. Для того, чтобы убрать фильтрацию, передайте методу значение `NULL`.

    <?php
    // Проводить профайлинг только тех запросы, которые отнимают по меньшей мере 5 секунд:
    $profiler->setFilterElapsedSecs(5);

    // Профайлировать все запросы безотносительно времени выполнения:
    $profiler->setFilterElapsedSecs(null);
    ?>

#### 6.2.3.2. Фильтрация по типу запроса

`setFilterQueryType()` дает разработчику возможность указывать, для каких типов запросов должны создаваться профайлы; для обработки нескольких типов запросов используйте логическое `OR`. Типы запросов определены в следующих константах `Zend_Db_Profiler`:

- `Zend_Db_Profiler::CONNECT`: операции по установке соединения или выбора базы данных.
- `Zend_Db_Profiler::QUERY`: обычные запросы к базе данных, которые не подходят к другим типам.
- `Zend_Db_Profiler::INSERT`: любые запросы, которые добавляют новые данные в базу данных; как правило, это команда INSERT.
- `Zend_Db_Profiler::UPDATE`: любые запросы, которые обновляют существующие данные, обычно это команда UPDATE.
- `Zend_Db_Profiler::DELETE`: любые запросы, которые удаляют существующие данные, обычно это команда DELETE.
- `Zend_Db_Profiler::SELECT`: любые запросы, которые извлекают существующие данные, обычно это команда SELECT.
- `Zend_Db_Profiler::TRANSACTION`: любые операции с транзакциями, такие, как начало транзакции, фиксация транзакции или откат.

Как и в случае `setFilterElapsedSecs()`, вы можете удалить все фильтры посредством передачи `NULL` в качестве единственного аргумента.

    <?php
    // профайлинг только запросов SELECT
    $profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);

    // профайлинг запросов SELECT, INSERT и UPDATE
    $profiler->setFilterQueryType(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

    // профайлинг запросов DELETE (так мы можем определить, почему удаляются данные)
    $profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);

    // удалить все фильтры
    $profiler->setFilterQueryType(null);
    ?>

#### 6.2.3.3. Получение профайлов по типу запроса

Использование `setFilterQueryType()` может сократить количество генерируемых профайлов. Тем не менее, иногда может быть полезным хранить все профайлы, но просматривать только те, которые нужны в данный момент. Другой метод `getQueryProfiles()` -- это то, что может делать такую фильтрацию "на лету", ему передается тип запроса (или логическая комбинация типов запросов) в качестве его первого аргумента; список констант типов запросов см. Раздел 6.2.3.2, «Фильтрация по типу запроса».

    <?php
    // Получение только профайлов запросов SELECT
    $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);

    // Получение только профайлов запросов SELECT, INSERT и UPDATE
    $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

    // Получение профайлов запросов DELETE (так мы можем определить, почему удаляются данные)
    $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
    ?>

Пред. | Уровень выше | След.
Глава 6. Zend_Db | Начало | 6.3. Zend_Db_Select