Пара слов об оптимальной архитектуре сайтов для работы с большими объемами информации в связке apache + php + mysql.

Оптимизация

Проекты, предоставляющие большие объемы информации в свободном доступе (каталог интернет-магазина, ежедневно пополняемая новостная лента, посещаемый форум, блог и т.д.), требуют оптимальной реализации работы с ней. Загрузка страницы блога, в котором всего 5000 записей, может длиться и все 10 секунд, тратя практически все это время на не оптимально составленный SQL запрос. В идеале, веб-сайт должен работать одинаково быстро, вне зависимости от объема хранимых данных, в рамках установленных пределов (количества элементов данных, на которые проект должен быть рассчитан).

ТЗ

Реализация оптимальной работы начинается на стадии составления ТЗ: за счет мощности сервера, способов вывода информации, ограничения функционала. Функционал, который будет предоставлять проект, должен быть четко представлен и ограничен, чтобы можно было выбрать подходящий способ оптимизации: что будут представлять собой элементы данных, как будет организован их постраничный вывод, сортировка, какими будут варианты их представления (в списке, на отдельной странице и т.д.).

Кэш

Хорошо, если есть возможность хранить страницы с информацией в статике, кэшируя контент сайта. Собирать страницу один раз, и выдавать для показа заранее собранные страницы. Страницу можно разбить на элементы данных, и кэшировать их. Такая возможность есть не всегда, но она решает проблему скорости. При этом возникает другая проблема — обновление КЭШа после изменения информации. Для этого можно написать скрипт, который будет исполняться ночью и синхронизировать данные в БД с данными в КЭШе. Но такой вариант не доступен, когда проект должен быть интерактивным. Например, делая КЭШ в блоге, необходимо обновлять его сразу после редактирования элемента данных, чтобы пользователь сразу видел новое или измененное сообщение. В этом случае обновлять в КЭШе нужно только отдельный, отредактированный элемент, и все данные, закэшированные в этом элементе, обновляются только при его редактировании или статичны.

  1. Кэш не обязательно должен быть HTML. Можно, например, реализовать некоторую динамику в элементе КЭШа, храня его в виде XML, и обрабатывая вывод с помощью XSLT.
  2. Не стоит зацикливаться на кэшировании данных со сложной структурой или элементами динамики, разбивая элемент КЭШа на несколько файлов, например. Кэшированная страница загружается быстрее, т.к. она уже составлена из динамических данных, и на это не тратится время при загрузке: прочитать и вывести один файл быстрее, чем обработать запрос на данные нескольких таблиц. Но файловая система работает медленнее, чем СУБД. Вполне вероятно, что сложный кэш будет загружаться дольше, чем динамически сформированная страница.
  3. Даже работу с кэшом можно оптимизировать. Например, если стоит задача вывести имена файлов из папки по порядку в php4, мы читаем папку функцией readdir(), добавляем результат в массив как значение — $list[] = $file_name и сортируем массив.
    $folder = opendir('folder/');
    $list = array();
    while ($file = readdir($folder)) {
      if ($file != '.' && $file != '..') {
        list($file_name, $file_ext) = explode('.', $file);
        $list[] = $file_name;                    
      }
    }
    closedir($folder);    
    sort($list);
    
    Однако если мы будем добавлять результат в массив как ключ — $list[$file_name] = 1 — сортировка по ключу будет быстрее процентов на 30%.
    $folder = opendir('folder/');
    $list = array();
    while ($file = readdir($folder)) {
      if ($file != '.' && $file != '..') {
        list($file_name, $file_ext) = explode('.', $file);
        $list[$file_name] = 1;                    
      }
    }
    closedir($folder);    
    ksort($list);
    

БД

В любом случае, при работе с динамикой или статикой, данные хранятся в БД, а в КЭШе только дублируются. Поэтому обязательно оптимизировать хранение данных и запросы к ним.

  1. Практически для всех проектов удачно подойдет формат таблиц My ISAM. Выбирать более подходящий формат имеет смысл в проектах, объемы данных в таблицах которого будут превышать 100MB.
  2. Если в таблице множество столбцов, одни из которых будут использоваться чаще, а другие реже, то стоит разбить такую таблицу на две. Это ускорит работу с часто запрашиваемыми данными. Например, если мы должны хранить имя, логин и пароль пользователя, которые будут запрашиваться очень часто, а так же разнообразную личную информацию о пользователе, которая будет запрашиваться только в одном разделе на сайте, то мы создаем две таблицы, соответственно.
  3. Избегайте использования NULL, старайтесь объявлять столбцы как NOT NULL. Если использование NULL необходимо, то избегайте наличия NULL как значения по умолчанию.
  4. Необходимо правильно выбирать типы данных при проектировке таблиц, стараясь сократить размеры хранимой информации. Например, UNSIGNED MEDIUMINT часто лучше, чем INT. Особое внимание при этом нужно уделить будущим первичным ключам и индексам.
  5. Первичным ключом в таблице лучше устанавливать один столбец. Первичный ключ на двух и более столбцах имеет смысл, когда столбцы являются внешними ключами, первичными ключами других таблиц, а текущая таблица хранит их соответствие друг другу (links).
  6. На этапе тестирования уже готового проекта нужно построить в таблицах индексы на столбцах, которые в запросах указаны в WHERE и ORDER BY. Для тестирования можно заполнить базу данными в объеме, на который проект должен быть рассчитан, и тестировать все запросы SELECT, которые выполняются в проекте. Необходимо проверить, правильно ли СУБД обрабатывает выборку и сортировку по индексируемым полям, используя оператор EXPLAIN.
  7. Если в таблице есть столбец, являющийся внешним ключом (FOREIGN KEY), обязательно постройте по нему индекс.

Я беру максимальное время загрузки страницы = 3 секунды.

Удачи ;)