#php #mysql #codeigniter #codeigniter-datamapper
#php #mysql #codeigniter #codeigniter-datamapper
Вопрос:
Я использую CodeIgniter и DataMapper для управления отношениями для магазина электронной коммерции. Отношения:
В продукте много артикулов, В продукте много amazon_products, В артикуле много amazon_products
Я пытаюсь извлечь все данные из базы данных и отформатировать их для использования Backbone на интерфейсе. В конечном итоге я хочу отправить json на страницу в следующем формате:
Array of products
Product
Array of amazon_products
Array of skus
Array of amazon_products
Product
Array of amazon_products
Array of skus
Array of amazon_products
Product
Array of amazon_products
Array of skus
Array of amazon_products
В настоящее время я генерирую эти данные с помощью следующего PHP-кода:
$products = new Product();
$products->order_by('ext_created_on', 'desc')->get();
$data['products'] = array();
foreach($products as $product){
$product_array = $product->to_array();
$product_array['amazon'] = $product->amazon_product->get()->all_to_array();
foreach($product->sku->get() as $sku){
$sku_array = $sku->to_array();
$sku_array['amazon'] = $sku->amazon_product->get()->all_to_array();
$product_array['skus'][] = $sku_array;
}
$data['products'][] = $product_array;
echo memory_get_usage()."<br>"
}
$data['products'] = json_encode($data['products']);
Когда я отслеживаю память моего сервера Ubuntu при выполнении этого, кажется, что он использует много (~ 13% памяти). Кроме того, поскольку в базе данных около 700 продуктов, DataMapper выполняет 1000 запросов, чтобы получить все эти данные. Являются ли запросы причиной большого использования памяти? Или есть что-то, что я упускаю из виду в foreach
цикле, что может привести к утечке памяти в памяти?
Результат get_memory_usage()
равен 33678176 после первого цикла продукта и 109580968 после последнего.
Ответ №1:
На случай, если кто-нибудь столкнется с этим, я смог сократить использование памяти примерно до 1/3, используя clear()
метод DataMapper. Я просто добавил строку $product->clear()
в конце внешнего foreach
цикла.
Я также добавил a $sku->clear()
в конце внутреннего цикла.
Ответ №2:
Хотя я никогда не использовал используемую вами библиотеку DataMapper, вы упомянули, что для получения результатов выполняются тысячи запросов. Исходя из этого, кажется, что, возможно, есть лучший метод, чем get() для извлечения $product-> sku и $sku-> amazon_product . Ваш первый get() в строке # 2 не получает всю информацию для вас? Я думаю, что get() не проверяет наличие доступных значений результата и что другая функция в вашем DataMapper может ссылаться на доступный набор результатов перед выполнением дополнительных вызовов к базе данных.
На самом деле, мне интересно, кэшируется ли уже $product->sku со значением для sku.
Комментарии:
1. Спасибо за отзыв axiom82. Первый get() получает все продукты. Он не содержит информации о каких-либо связанных моделях. Для этого, я полагаю, мне нужно перебирать каждый продукт с первого get() и вызывать get() для его свойства sku. Вот документы, если вам интересно: datamapper.wanwizard.eu . Я тоже чувствую, что должен быть более эффективный способ получения этих данных, но я в тупике, что это может быть. Однако в библиотеке есть
$autopopulate_has_many
функция, я полагаю, что она по-прежнему будет выполнять те же запросы, только без необходимости вручную вызывать get() для этого.2. Если вы уверены в написании запросов без datamapper или уверены в написании своих собственных или попытке другого, это может быть другим вариантом. Я использую MVC, поэтому у меня есть папка / models с файлами классов php, в каждом из которых есть методы для запроса к базе данных и возврата набора данных. Несмотря на то, что ORM хорош, его удобство для пользователя может повлиять на производительность. Я бы выбрал класс с методами, каждый метод возвращает определенный набор результатов из вашей базы данных. Чтобы свести ваши запросы к базе данных к нескольким, вы даже можете написать пользовательские объединения, чтобы объединить большую часть вышеперечисленного в один запрос.