Сделал я недавно некий тест, который выдал любопытные данные. Коими хочу поделиться, дабы помочь многим прояснит спорные ситуации.
Везде только и пишут, что насколько быстры массивы, насколько медлителен Active Record… Но когда видишь конкретные цифры гораздо легче понимать что на сколько лучше другого.
Есть цикл из миллиона(1 000 000) итераций. На каждой итерации:
Объявляется новый объект и заполнялся данными.
$address = new Address();
Используется паттерн singlton — объект объявляется один раз и на каждой итерации и перезаполняется.
$address = Address::model();
Объявляется и заполняется массив.
$address = array();
Простой stdClass().
$address = new stdClass();
Объявляем объект (как в варианте 1) но без инициализации всех сопутствующих данных AR
$address = new Address(null);
Результаты (сек.):
28.490615844727
7.2354989051819
4.5744869709015
5.9930000305176
9.5185680294037
Выводы:
Конечно же для хранения и обработки данных можно использовать объекты, а не только массивы.
Конечно же классы можно наследовать от CActiveRecord, даже если не собираешься использовать классический подход Active Record – для этого не забываем добавлять null в конструктор (обращаю внимание — не false, не пустую строку, не 0):
$address = new Address(null);
и избегать записи:
$address->attributes = $_POST['Address']
т.к. при этом все равно происходит подключение мета данных AR и увеличиться время работы объекта.
Делаем присвоение в ручную:
$address->street = $_POST['Address']['street'];
Конечно же нужно использовать метод – model() – Осторожно! Это касается Yii < v.2
Не стоит упираться только в массивы – их тоже надо использовать с умом. По удобству они не идут практически ни в какое сравнение с объектами.
Самый главный вывод в том, что надо всегда (включать мозги) находить «золотую середину» между скоростью разработки продукта и скоростью работы продукта. К примеру, если в день нет хотя бы 50 000 посещений и нет выводов списков каких-то данных из базы на сайте, то про массивы вообще можно забыть и не вспоминать пока не появиться узкое место и не будет тормозов.
Хочется узнать, почему же класс, наследуемый от ActiveRecord тратит так много времени. В результате тестов, мы видим, что в основном время затрачивается на инициализацию/присвоение свойств/элементов, т.е. чем больше приходится использовать свойств/элементов тем дольше будет работать объект/массив. А поскольку ActiveRecord должен описывать в себе все поля таблицы (для этого существует классы CActiveRecordMetaData и CmysqlTableSchema и CmysqlColumnSchema у которых своих свойств дофига), то на это описание мета данных и тратиться основное время исполнения класса наследуемого от ActiveRecord.
Из этого можно сделать
еще Выводы:
Чем больше столбцов в таблице, которую будет поднимать ActiveRecord, тем дольше наш класс будет инициализироваться.
Обратите внимание, что это не зависит от того, сколько вы полей поставите в SELECT – мета данные в любом случае будут подниматься все (если я, конечно, не ошибаюсь). И на против, от количества полей в SELECT будет напрямую зависеть скорость работы DAO.
Обращаю внимание, что этот тест затрагивает только php и никоем образом не зависит оптимизаций mysql или apache.
Стоит учитывать то, что временные данные тестов это не идеальное время работы массива или объекта в идеальных условиях, но позволяют сравнить скорость работы относительно друг друга.
PPS
Класс Address() выдуман и свойства выбраны приблизительно по смыслу.