Pull to refresh

Comments 6

php / oracle это странная связка, очень много проблем огреб. Довелось начинать проект с oracle в качестве базы, с планами миграции на mysql в дальнейшем. Единственный ORM который осилил oracle — propel orm. Благо этап oracle пройден, данные успешно перенесены в mysql.
Тоже довелось немало использовать связку PHP и Oracle (причем именно с Yii 1). Почему-то этот стек любят гос. структуры в России для разработки своих приложений. Да и еще на Windows / IIS все это дело крутится. Проблемы конечно были, например с Prepared statements. Бывало при передаче параметров запрос мог выполняться в десятки(!) раз медленнее чем при прямой вставке значений.

Но в целом могу сказать что дело привычки. Просто нужно научиться его готовить.
Бывало при передаче параметров запрос мог выполняться в десятки(!) раз медленнее чем при прямой вставке значений.

Это нормальное поведение Oracle независимо от типа клиента. Так работает стоимостной оптимизатор запросов Oracle.

Если вы передаете значения литералами, то Oracle строит план запроса каждый раз, при этом построение плана запроса — довольно затратная операция и для многих запросов может занимать больше времени чем собственно выборка данных.
Поэтому для уменьшения общей нагрузки на сервер рекомендуется использовать bind-переменные. В таком случае Oracle анализирует значения переменных первый раз, и строит план, а при дальнейших вызовах идентичного запроса с любыми значениями переменных (даже из других сессий) использует ранее созданный план.

Но это не всегда оправдано.
Предположим вы делаете запрос по большой (миллионы записей) таблице заказов с условием по двум полям — customer_id и order_date в диапазоне. Количество уникальных клиентов — десятки тысяч, история заказов за много лет. У вас есть индекс в таблице и по каждому из полей — client_id и order_date.

При первом вызове вы передали диапазон дат в 1 день, и client_id клиента с очень большой историей заказов. Оптимизатор проанализировал статистику данных и решил использовать индекс по дате, так как выгоднее перебрать все заказы за 1 день, чем все заказы клиента за много лет. Такой план сохранился в кеше запросов Oracle.

При одном из последующих вызовов вы передали в bind-переменные диапазон дат длинной в год и другой client_id. И хотя у этого клиента за всю историю всего несколько заказов, используется все равно индекс по дате. В итоге перебираются все заказы всех клиентов за год (сотни тысяч записей), что занимает в десятки раз больше времени, чем перебор всех заказов (за всю историю) этого конкретного клиента. Если бы параметры передавались литералами, то план запроса был бы создан заново, использовался бы индекс по client_id, и конечно такой запрос выполнился бы во много раз быстрее.

До 10-й версии данная проблема стояла довольно остро, в более поздних версиях были попытки как-то эту проблему решить.
А phppdo не пробовали? Он умеет clob/blob в Oracle. Либа старая, но с yii 1.1 работает нормально.
Хотя у вас вроде тоже нормально получилось.
Не всегда есть возможность использовать PDO, например у нас php 5.2.17 где драйвер для oracle в экперементальном виде. Были проблемы с передачей больших xml в процедуры oracle с PDO.
Sign up to leave a comment.

Articles