Этот пост только для 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 может выиграть по скорости и при миллионе элементов.