Как работают подготовленные заявления? - PullRequest
5 голосов
/ 10 сентября 2008

Я пишу некоторые процедуры БД и использую подготовленные операторы. Моя среда - PDO с PHP5.

Я понимаю, что подготовленные операторы в первую очередь обеспечивают выигрыш в производительности, а также некоторые вспомогательные бонусы, такие как отсутствие необходимости вручную экранировать входные данные SQL.

У меня вопрос по поводу исполнения.

У меня есть две реализации функции getPrice, которая берет идентификатор продукта и возвращает его цену.

getPrice_A повторно использует один и тот же объект PDOStatement при последующих вызовах в рамках одного и того же выполнения скрипта. Это необходимо или рекомендуется? Если да, есть ли способ избежать дублирования этого дополнительного кода в каждом get * () в каждой отдельной модели?

getPrice_B создает новый объект PDOStatement при каждом вызове. Примет ли СУБД, что это утверждение уже подготовлено, и все еще сможет пропустить какую-то работу? Другими словами, правильно ли эта реализация использует преимущества производительности подготовленных операторов?

Написав все это и прочитав его, я думаю, что getPrice_B - это хорошо, а getPrice_A предоставляет незначительную выгоду в дополнение к этому, что может или не может стоить дополнительных сложностей.

Я все еще хотел бы услышать наверняка от кого-то более знающего.

Предположим, что $pdo является действительным подключенным объектом PDO в примерах ниже.

<?php
class Product {
    static function &getPrice_A($id) {
        static $stmt;
        if (!$stmt) {
            $stmt = $pdo->prepare('SELECT price FROM products WHERE id = ?');
        }
        $stmt->execute(array($id));
        return $stmt->fetchColumn(0);
    }

    static function &getPrice_B($id) {
        $stmt = $pdo->prepare('SELECT price FROM products WHERE id = ?');
        $stmt->execute(array($id));
        return $stmt->fetchColumn(0);
    }
}

// example usage:
$price = Product::getPrice(4982);
echo "Product 4982 costs $price\n";

1 Ответ

3 голосов
/ 10 сентября 2008

Из того, что я понимаю, подготовленные операторы будут повторно использовать сгенерированный план SQL, если это тот же оператор, поэтому база данных будет видеть тот же подготовленный оператор и не должна выполнять работу, чтобы выяснить, как запросить базу данных. Я бы сказал, что дополнительная работа по сохранению подготовленного оператора в Product::getPrice_A обычно не очень полезна, скорее потому, что она может затенять код, а не проблему производительности. Работая с производительностью, я чувствую, что всегда лучше сосредоточиться на ясности кода, а затем на производительности, когда у вас есть реальная статистика, указывающая на проблему.

Я бы сказал: «Да, дополнительная работа не нужна» (независимо от того, действительно ли она повышает производительность). Кроме того, я не очень большой эксперт по БД, но прирост производительности подготовленных операторов - это то, что я слышал от других, и это на уровне базы данных, а не на уровне кода (поэтому, если код фактически вызывает параметризованный оператор для фактическая БД, тогда БД может выполнять кэширование этих планов выполнения ... хотя в зависимости от базы данных вы можете получить преимущество даже без параметризованного оператора).

В любом случае, если вы действительно беспокоитесь (и видите) проблемы с производительностью базы данных, вам следует поискать решение для кэширования, которое я очень рекомендую memcached . С помощью такого решения вы можете кэшировать результаты запроса и даже не попадать в базу данных, к которым вы часто обращаетесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...