Для тех, кого беспокоит количество запросов к БД

Аватар пользователя kosilko kosilko 2 апреля 2009 в 14:47

Недавно обнаружил, что переводы можно содержать не в БД, а файле settings.php, строки прописанные в нем будут иметь преимущество над строками в БД. Таким образом, если поместить туда все строки из базы, то после этого можно совсем отключить модуль locale, и существенно сократить количество запросов, при этом имея полностью русский интерфейс. В общем, в результате у меня родилось такое решение:

выполняем такой код (экспорт из БД в php-массив):

<?php
if($r db_query('
SELECT s.source, s.location, t.translation  
FROM {locales_source} s 
INNER JOIN {locales_target} t 
ON s.lid=t.lid AND s.source<> t.translation  AND t.language=\'ru\' AND s.textgroup=\'default\' 
GROUP BY t.translation
LIMIT 0,10000'
)) {
$t = array();
while (
$rs=db_fetch_object($r)) {
    
$rs->location explode(':',$rs->location);// вычисляем файл-ичточник из записи типа "имя_файла:номер строки"
    
$file_ext drupal_strtolower(trim(strstr(trim($rs->location[0]),'.'))); // узнаем расширение файла-источника перевода
    
if ($file_ext!='.info' && $file_ext != '.install')  // исключаем .info и .install файлы
{
        if (
        !isset(
$t[$rs->source])
        &&
        
trim($rs->source)!=''&&trim($rs->translation)!=''&&$rs->source!=NULL&&$rs->translation!=NULL //проверяем на всякий случай на предмет пустых строк
        
) {
            
$t[$rs->source] = $rs->translation;
        }
    }
}
echo 
'$conf[\'locale_custom_strings_ru\'] = ';
var_export($t);
echo 
';';
die;
}
?>

результат копируем в хвост файла settings.php, не забываем при этом про UTF8. Отключаем модуль locale (можно и не отключать) , и собственно все. Правда, в итоге у меня получился файл размером 700 с лишним килобайт, это наверное великовато, и большого прироста производительности это не принесет, но тут я повторюсь - это решение должно помочь тем, у кого проблемы с большим количеством запросов, а такое бывает на бесплатных хостингах.

Комментарии

Аватар пользователя Azerot Azerot 2 апреля 2009 в 14:58

Угу, знаю такую фичу.
Я бы на вашем месте не всё выгружал, а только строки, касающиеся публичной части. Тогда реально и размер будет небольшим и количество запросов можно уменьшить. Хотя надо ещё понимать, что есть кэширование.

Аватар пользователя kosilko kosilko 2 апреля 2009 в 15:05

"Azerot" wrote:
бы на вашем месте не всё выгружал, а только строки, касающиеся публичной части. Тогда реально и размер будет небольшим и количество запросов можно уменьшить.

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

"Azerot" wrote:
Хотя надо ещё понимать, что есть кэширование.

кэш имеет свойство обновляться, и тут опять имеем кучу запросов. В этот момент на бесплатном хостинге срабатывает защита, и сайт в дауне.. у меня была такая проблема на 000webhost.com, сайт блокировался и на почту кидалось уведомление что у вас много запросов к базе.

Аватар пользователя Dan Dan 2 апреля 2009 в 15:36

"Уж сколько раз твердили миру...".

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

Ещё не забываем, что весь файл будет сидеть в памяти - на дешёвых хостингах её полно?

Аватар пользователя bratello bratello 2 апреля 2009 в 16:27

Можно все это скинуть в ХМЛ, и подгружать одноразово, поиск в ХМЛ довольно таки шустро работает. Жаль что референс на обьект ХМЛ документа нельзя сохранить в сесси, или где то в глобале, как это на АСП делалось раньше - тогда бы локейл поднимался всего один раз. Вообще в ПХП референсы в сессии не помешали бы, но приходится только мечтать...

Аватар пользователя kosilko kosilko 2 апреля 2009 в 16:32

"Dan" wrote:
По вашему, загрузка и парсинг средствами PHP несколько сот килобайтного файла будет работать быстрее,

мерял вчера, прироста скорости нет, но и замедления тоже не увидел... если вам не лень - можете померять. Я ж сказал, что все это только для уменьшения запросов к базе, а вы воспринимаете это как будто я тут пытаюсь впарить некую панацею от всех бед Smile
А насчет памяти, сколько он там займет? Метр, 2 метра или все десять?

Аватар пользователя bratello bratello 2 апреля 2009 в 17:44

Кстати, в случае с ХМЛ прирост производительности должен быть приличный, не прийдется за каждым стрингом лазить в базу, но прийдется всего один раз загрузить ХМЛ документ, поиск нужной строки можно осуществлять XPath query, если указывать точный путь то поиск будет очень шустрым.

Аватар пользователя Dan Dan 2 апреля 2009 в 20:14

"kosilko" wrote:
а вы воспринимаете это как будто я тут пытаюсь впарить некую панацею от всех бед =)

Этот флаг подхватывают с незапямятных версий друпала. На моей памяти - с 4.6 (с этой версии началось знакомство с Друпал).На д.орг много было дискуссий на эту темы, ты не первый, но переводы всё таки в базе Smile

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

Аватар пользователя Azerot Azerot 2 апреля 2009 в 21:55

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

Будет. Например в случае использования eAccelerator. Потому как всё уже распарсилось и лежит в shared memory. Далее, в корне неверно рассматривать MySQL как нечто идеализированно быстрое. При хорошей нагрузке на хостинг, MySQL тормозить будет значительно быстрее, чем файловые операции и процессор.

Аватар пользователя Demimurych Demimurych 2 апреля 2009 в 23:15

"Dan" wrote:
Уж сколько раз твердили миру...".

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

Ещё не забываем, что весь файл будет сидеть в памяти - на дешёвых хостингах её полно?

Если я ничего не забыл, то локаль хранится чаще всего в кеше в упакованном блобе, который потом распаковывается. Но я мог с чем то и попутать.

Как уже сказали Выше. Все очень сильно зависит от того как настроен хостинг. Я могу привести примеры конфигурация где mysql будет выгоднее использовать и напротив где предложенный способ.

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

Аватар пользователя Dan Dan 3 апреля 2009 в 2:58

"Azerot" wrote:
Будет. Например в случае использования eAccelerator. Потому как всё уже распарсилось и лежит в shared memory.

Ну дык и таблицы в память засунуть можно (а некоторые - нужно) и будет там всё проиндексированное лежать.

"Azerot" wrote:
При хорошей нагрузке на хостинг, MySQL тормозить будет значительно быстрее, чем файловые операции и процессор.

Если тормозит MySQL, думаю, разумней будет заняться ег оптимизацией, нежели нагружать проц и расходовать память.

"Demimurych" wrote:
Как уже сказали Выше. Все очень сильно зависит от того как настроен хостинг. Я могу привести примеры конфигурация где mysql будет выгоднее использовать и напротив где предложенный способ.

Приведите. Я думаю эта информация пригодиться многим. Настройки хостинга, безусловно, влияют очень сильно.

Аватар пользователя Azerot Azerot 3 апреля 2009 в 8:07

> Если тормозит MySQL, думаю, разумней будет заняться ег оптимизацией, нежели нагружать проц и расходовать память.
На виртуальном хостинге? Как вы себе это представляете? Smile
А ведь большинство именно на виртуальном хостинге сидят.

MySQL выгодно использовать, когда на сервере (я опять имею в виду виртуальный хостинг)
1. мало народу сидит (соответственно MySQL не нагружен и во всю используется query_cache)
2. при соблюдении 1-го условия, PHP выполняются в mod_php или на крайний случай в fastCGI
3. Если диск, где лежат сами файлы сайта оооочень тормозной

Во всех остальных случаях файловые операции будут проходить быстрее, потому что:
1. Не требуется открытие соединения к БД
2. Не требуется постановка запроса к БД в очередь MySQL и соответственно ожидание ответа
3. Там где не поможет eAccelerator с высокой долей вероятности поможет кэш чтения операционной системы

Так что преимущество такого метода очевидно. Единственное как я и писал, надо держать в файле только популярные строки перевода, а не все подряд, что сократит размер до 5-10 кбайт, соответственно со всеми вытекающими.

Аватар пользователя Dan Dan 3 апреля 2009 в 16:07

"Azerot" wrote:
На виртуальном хостинге? Как вы себе это представляете? :)

С трудом Smile

"Azerot" wrote:
А ведь большинство именно на виртуальном хостинге сидят.

Да, да ещё "русском" - куча лимитов, зато поддержка понятно говорит.

"Azerot" wrote:
Во всех остальных случаях файловые операции будут проходить быстрее, потому что:
1. Не требуется открытие соединения к БД
2. Не требуется постановка запроса к БД в очередь MySQL и соответственно ожидание ответа
3. Там где не поможет eAccelerator с высокой долей вероятности поможет кэш чтения операционной системы

1. Друпал по-любому соединение открывает.
2 и 3 - Когда MySQL загружен, то да, это позволит его немного разгрузить, но все эти телодвижения - плюс-минус километр. Слишком много частностей. Иначе ответ на вопрос "Как оптимизировать Друпал" был бы уже давно озвучен.

Аватар пользователя Azerot Azerot 3 апреля 2009 в 17:18

> Да, да ещё "русском" - куча лимитов, зато поддержка понятно говорит.
Ага. Я как человек, который знает о хостинге не понаслышке могу даже объяснить откуда лимиты и откуда цены. А клиенты у нас такие "квалифицированные", что поддержку надо только русскую, ибо только русский админ может вынести такое знание предмета клиентом и ещё при этом как-то разрулить ситуацию.

> но все эти телодвижения - плюс-минус километр.
А нет такого рецепта, который бы позволил сразу и в разы. Чуть-чуть здесь, чуть-чуть там, глядишь и 10-15% производительности набрали. Я вот, например, не уверен, что для таблиц, которые создают модули везде есть индексы где нужно. Ядро понятное дело вылизали, а вот насчёт модулей не уверен. Впрочем - это уже другая история.

А насчёт загрузки MySQL, я надеюсь никому тайны не открою, если скажу что на любом хостинге висит во главе top листа процессов, нагружающих систему? Он, родимый.

Аватар пользователя kosilko kosilko 3 апреля 2009 в 18:21

"Dan" wrote:
Более перспективным вариантом (в части производительности) мне кажется замена переводов непосредственно в модулях, хотя метод этот небезопасен.

мысль заманчивая, а чем небезопасно? Надо попробовать на досуге скрипт соорудить, чтоб рекурсивно парсил все файлы в папках друпала и подменял строки по массиву из сабжевого кода Smile

Аватар пользователя Dimm Dimm 3 апреля 2009 в 21:13

В модуле locale.module по умолчанию кэшируются строчки длинной менее 75 символов ...AND LENGTH(s.source) < 75...
$result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION);

хакнул locale.module чтобы кэшировать все строки
(...AND LENGTH(s.source) < 999...)
число запросов сократилось на 10-20%.

Кэширование строк длиной <75
Page execution time was 583.44 ms. Executed 167 queries in 148.53 milliseconds.
Page execution time was 534.43 ms. Executed 167 queries in 151.49 milliseconds.
Page execution time was 532.61 ms. Executed 167 queries in 146.53 milliseconds.

Кэширование всех строк
Page execution time was 534.24 ms. Executed 129 queries in 133.64 milliseconds.
Page execution time was 517.06 ms. Executed 130 queries in 123.81 milliseconds.
Page execution time was 567.35 ms. Executed 129 queries in 130.06 milliseconds.

Аватар пользователя bratello bratello 11 апреля 2009 в 17:09

"Dimm" wrote:
хакнул locale.module чтобы кэшировать все строки
(...AND LENGTH(s.source) < 999...)
число запросов сократилось на 10-20%.

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

Аватар пользователя Valeratal Valeratal 12 апреля 2009 в 11:42

к сожалению, далеко не везде, хостинг так тонко покупается
вот у меня, например, DDS, мой тариф 4000р, а следующий тариф в этой линейке, уже 7000 Smile

Аватар пользователя SVictor SVictor 20 октября 2010 в 15:16

Для дурных хостеров таки как у меня думаю, полезная фишка.
Утомили уже с подсчетом количества запросов, а ведь их действительно много.