Этот пост только для PHP-программеров. Остальным он будет непонятен.
В ObjectNuke используется схема дискового кеширования некоторых SQL-запросов. Я решил проверить эффективность этой схемы на различных масштабах.
Дело в том, что все проекты нашей фирмы работают на ReiserFS, которая сама по сути является БД с индексированием доступа к файлам. Поэтому у меня и встал вопрос: что эффективнее: один запрос к MySQL или одно считывание файла под ReiserFS?
Итак, я создал таблицу:
CREATE TABLE `skorost` (
`guid` bigint(20) unsigned NOT NULL default ‘0’,
`datatext` char(255) NOT NULL default ”,
`minitext` char(255) NOT NULL default ”,
`date` datetime NOT NULL default ‘0000-00-00 00:00:00′,
`size` bigint(20) unsigned NOT NULL default ‘1’,
PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251
Потом заполнил её и дисковый кэш вот этим скриптом:
chdir(dirname(realpath($_SERVER['PHP_SELF'])));
require ‘../conf/config.conf';
require_core(‘Sqlfunc.lib’);$conn = &getADO();
for ($i=0; $i < 1000000; $i++)
{
$sSql = ‘INSERT INTO answer(guid, datatext, minitext, date) VALUES (‘.$i.’, “‘.$i.'”, “‘.$i.'”, NOW())';
$conn->Execute($sSql);
if ($i % 10000 ==0) echo $i.”n”;
dcache::set(‘values’, $i, $sSql);
}
А потом тестировал время исполнения скриптов последовательного считывания всех значений из кэша и из БД (MySQL 4.1).
time ./test_reiser.php
time ./test_sql.php
Число элементов | Время | ReiserFS 3.6 (опции BORDER, SMALL_TAILS), секунды | MySql 4.1, секунды |
1000 | real | 0.112 | 0,16 |
user | 0.084 | 0,11 | |
system | 0.028 | 0,02 | |
100000 | real | 5,75 | 8,11 |
user | 2,48 | 2,54 | |
system | 3,11 | 0,96 | |
1000000 | real | 104 | 75,87 |
user | 25,67 | 24 | |
system | 62,88 | 8 | |
1000000 (не дефрагментированный результат) | real | 96,92 | 74,78 |
user | 25,89 | 23,94 | |
system | 63,11 | 8,86 |
Когда тестировался миллион элементов MySQL-база данных занимала 535 мегабайт, а индекс около 12 мегабайт. И то и другое помещалось в кэше. По данным df папка с файлами занимала 211 мб. А по данным du папка с файлами занимала 4,3 гб. Вот как эффективно умеет упаковывать маленькие файлы ReiserFS!
Выводы: Даже до тех пор пока число кешируемых элементов относительно велико (до сотни тысяч), имеет смысл использовать дисковое кэширование. Только в сервисах, где речь идёт о миллионах кешируемых элементов, начинает выигрывать MySql, да и то, если кэшируется результат всего одного запроса.
Нужно учесть следующие моменты:
- Лучше всего дисковое кеширование использовать, когда кешируется результат одного сложного или нескольких простых запросов. Причём кэшировать желательно уже сгенерированные куски HTML. А иначе загрузка CPU может повысится.
- Для большинства сайтов оно будет эффективно даже для одного запроса, так как у очень редких сайтов число кешируемых элементов более десяти тысяч.
- Если диск сильно дефрагментирован, то эффективность дискового кеширования снижается примерно на 10%, на скорость работы MySql это практически не влияет. Т.е. имеет смысл выделять отдельный диск или RAM-диск для папки дискового кеша.
Почему же при миллионе элементов MySql опередила ReiserFS? Если присмотреться к таблице то видно, что при 100 000 запросах время, которое ушло у ReiserFS на работу с файлами составило 3,11 секунды, а при 1 миллионе уже 62 секунды. Запросов увеличилось в 10 раз, а время в 20. Очевидно, что собака зарыта здесь. Видимо если в папке от 500 тысяч файлов, то эффективность работы ReiserFS падает.
Т.е. если разбивать кешируемые элементы по разным папкам (пространствам в терминах ObjectNuke), то, наверное, ReiserFS может выиграть по скорости и при миллионе элементов.