Архив за Июнь 2008

Кэширование в HTTP

Механизм кэширования применяется с целью опртимизации пересылки данных между клиентом и сервером. Запрошенный пользователем по HTTP-протоколу документ может быть сохранен в кэше промежуточного сервера или браузера, и при повторном его запросе будет выдаваться без обращения к источнику.

Кэши принято подразделять на два вида: локальные и глобальные. Локальный кэш создается браузером клиента, тогда как глобальный располагается на прокси-сервере провыйдера (или организации, в которой имеется свой внутренний прокси-сервер).

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

В большинстве случаев кэширование позволяет ускорить работу с Интернетом и значительно снизить трафик, но иногда кэширование может мешать работе web-приложений. Если посетители часто загружают страницы web-сайта с редко изменяющейся информацией, кэширование полезно, поскольку экономит трафик и сокращает время выполнения запроса. Если же посетитель загружает динамические страницы, например, активного форума, кэширование, без сомнения вредно.

Для подавления кэширования можно использовать HTTP-заголовки:

<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Дата в прошлом
header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
header("Cache-Control: no-cache, must-revalidate"); // HTTP 1.1
header("Pragma: no-cache"); // HTTP 1.0
?>

HTTP-заголовок Expires задает дату, по достижению которой документ считается устаревшим, поэтому задание для этого заголовка уже прошедшей даты предотвращает кэширование данной страницы.

HTTP-заголовок Last-Modified определяет дату последнего изменения страницы. Если с момента последнего обращения к ней прокси-сервера значение этого заголовка изменилось, происходит происходит повторная загрузка страницы, поэтому присвоение этой директиве текущего времени прикаждом обращении предотвращает кэширование.

HTTP-заголовок Cache-Control предназначен для управления кэшированием, и указание его значения равным no-cache также приводит к запрету кэширования. В устаревшем стандарте HTTP 1.0 для запрета кэширования нужно присвоить значение HTTP-заголовку Pragma.

Уменьшение количества цветов в изображении

Часто для оптимизацации изображения или достижения плакатного эффекта количество цветов в гамме сокращают. В библиотеке GDLib для этого предназначена функция imagetruecolortopalette(). Напишем небольшой скрипт, который принимает единственный параметр $_GET['color'], равный количеству цветов в конечном изображении.

<?php
if ( !isset( $_GET['color'] ) )
  $color = 256;
else
  $color = (int)$_GET['color'];
// Проверяем корректность параметра $_GET['color']
if( $color < 2 ) $color = 2;
if( $color > 256 ) $color = 256;
// Создаем изображение на основе существующего
$image = imagecreatefromjpeg( 'image.jpg' );
if( $image ) {
  // Уменьшаем количество цветов
  imagetruecolortopalette( $image, true, $color );
  // Отправляем HTTP-заголовок Content-type
  header( 'Content-type: image/gif' );
  // Выводим изображение в браузер
  imagegif( $image );
  // Уничтожаем изображение в памяти
  imagedestroy( $image );
}
?>

Файл index.html демонстрирует работу скрипта:

<img src="image.jpg" alt="" />
<img src="image.php?color=60" alt="" /><br/>
<img src="image.php?color=30" alt="" />
<img src="image.php?color=15" alt="" /><br/>
<img src="image.php?color=5" alt="" />
<img src="image.php?color=2" alt="" />

Полнотекстовой поиск в MySQL

Полнотекстовой поиск в MySQL на сегодняшний день поддерживается только для таблиц типа MyISAM и только для текстовых столбцов переменной длины (TEXT и VARCHAR). Эта возможность активируется созданием индекса FULLTEXT для столбцов, по которым необходимо осуществлять поиск.

Полнотекстовой поиск в MySQL не чувствителен к регистру. Кроме того, при поиске игнорируются так называемые “общеупотребительные” слова. К ним относятся слишком короткие слова (по умолчанию состоящие меньше, чем из четырех символов), а также слова, встречающиеся, по крайней мере, в половине записей. Так если в таблице имеются только две записи, то поиск не даст результатов, поскольку каждое слово будет присутствовать в половине записей.

Для использования возможности полнотекстового поиска в таблице, содержащей текстовые поля, необходимо создать индексы FULLTEXT. Изменить уже существующие таблицы можно при помощи оператора ALTER:

ALTER TABLE mytable ADD FULLTEXT name (name);

Здесь сразу после ключевого слова FULLTEXT следует имя создаваемого индекса, за которым в скобках указано имя текстового столбца.

Индекс FULLTEXT можно создать сразу по нескольким столбцам. Для этого в скобках после имени индекса нужно указать имена двух столбцов через запятую:

ALTER TABLE mytable ADD FULLTEXT name (name, description);

Если индекс создается только по одному столбцу и его имя совпадает с именем столбца, то имя индекса, размещенного после ключевого слова FULLTEXT, можно опустить.

На количество индексов в таблице ограничения также не накладываются, допустимо создание нескольких индексов:

ALTER TABLE mytable ADD FULLTEXT (name),
                    ADD FULLTEXT (description),
                    ADD FULLTEXT together (name, description);

Поиск выполняется при помощи встроенной функции MATCH(), в качестве аргумента которой выступает один или более индексов типа FULLTEXT, а также функции AGAINST(), которая принимает в качестве аргумента искомую строку:

SELECT * FROM mytable WHERE MATCH(name) AGAINST('программирование');

Здесь из таблицы mytable извлекаются все записи, поле name которых содержит слово “программирование”. Синтаксис допускает использование нескольких конструкций MATCH() - AGAINST() после оператора WHERE, разделенных логическими операторами OR или AND:

SELECT * FROM mytable WHERE MATCH(together) AGAINST('программирование')
                         OR MATCH(together) AGAINST('кодирование');

Здесь из таблицы mytable извлекаются все записи, поля name или description которых содержат либо слово “программирование”, либо слово “кодирование”.

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

Начиная с версии 4.0.1 MySQL поддерживает поиск в так называемом логическом режиме, позволяющем задать обязательное отсутствие слова в результатах запроса, изменять величину релевантности для отдельных слов и многое другое.

Ссылки по теме: