Рекомендация CakePHP выполнить итерации огромной таблицы и генерировать карту сайта?

Я пытаюсь создать использование карты сайта XML CakePHP от таблицы, которая имеет больше чем 50 000 записей в данный момент, каждый рекордный эквивалент URI в карте сайта. Теперь проблемой, с которой я сталкиваюсь, является CakePHP, выполняет меня из памяти при генерации его, по двум причинам:

  1. A find('all') создает огромный ассоциативный массив всего набора 50,000 URIs.
  2. Так как я не хочу производить HTML от самого контроллера, я передаю ассоциативный массив, содержащий URI, приоритет, частота изменения и т.д., к представлению с a $this->set() звоните - который снова огромен, содержа 50 000 индексов.

Действительно ли возможно вообще, сделать это при следовании за MVC и инструкциями CakePHP?

6
задан tereško 10 February 2013 в 13:59
поделиться

4 ответа

Вы уверены, что вам не хватает памяти для 50 000 записей? Даже если размер строки составляет 1 КБ (довольно большой), вам придется иметь дело с ~ 50 МБ данных? У моего P1 было достаточно оперативной памяти, чтобы справиться с этим. Установите memory_limit в php.ini выше значения по умолчанию. (Рассмотрите также возможность настройки max_execution_time.)

С другой стороны, если вы считаете набор данных слишком большим и обрабатываете его слишком ресурсоемким, вам не следует обслуживать эту страницу динамически, это идеальная приманка для DDoS-атак. (По крайней мере, я бы сильно кэшировал его.) Вы можете запланировать задание cron для повторного создания страницы каждые X часов с помощью сценария на стороне сервера, свободного от штрафа MVC за одновременную передачу всех данных в представление, он мог работать со строками последовательно.

2
ответ дан 8 December 2019 в 18:35
поделиться

На этой неделе у меня была похожая проблема, и я наткнулся на поведение Containable . Это позволяет сократить количество запросов, связанных с отношениями (если они у вас есть).

Лучшим решением было бы программно использовать LIMIT и OFFSET и перебирать небольшие фрагменты набора записей за раз. Это избавляет вас от необходимости сразу загружать в память 50К записей.

3
ответ дан 8 December 2019 в 18:35
поделиться

find ('all') слишком жадный, вам придется быть более конкретным, если вы не хотите исчерпать память.

Как указано выше, используйте поведение Containable. Если вам нужны только результаты из вашей таблицы (без связанных таблиц) и только для пары полей, более явный запрос, подобный этому, должен быть лучше:

$results = $this->YourModel->find('all', array(
    'contain' => false,
    'fields' => array('YourModel.name', 'YourModel.url')
);

Вам также следует рассмотреть возможность добавления механизма кеширования HTML (cakePHP имеет встроенный или используя метод , предложенный Мэттом Карри ).

Конечно, это будет кэшированная версия, и она не будет полностью соответствовать вашему списку. Если вам нужен больший контроль, вы всегда можете сохранить результат в кеше торта (используя Cache :: write ), используя обратные вызовы afterSave / afterDelete вашей модели для обновления кэшированного значения и воссоздания кешированного файла xml отсюда. .

2
ответ дан 8 December 2019 в 18:35
поделиться

Вы пробовали unBindModel (если у вас есть отношения) ...

Когда мне нужно делать огромные запросы в cakephp, я просто использую "обычный" mysql-функции, такие как mysql_query, mysql_fetch_assoc и т. д. Намного быстрее и без недостатка памяти ...

1
ответ дан 8 December 2019 в 18:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: