У меня есть веб-приложение на основе PHP / MySQL, которое поддерживает несколько языков с помощью таблицы MySQL «language_strings» с полями string_id, lang_id, lang_text. Затем я вызываю следующую функцию, когда мне нужно отобразить строку на выбранном языке …
public function get_lang_string($string_id,$lang_id) { $db=new Database(); $sql=sprintf("SELECT lang_string FROM language_strings WHERE lang_id IN (1, %s) AND string_id=%s ORDER BY lang_id DESC LIMIT 1", $db->escape($lang_id, "int"), $db->escape($string_id,"int")); $row=$db->query_first($sql); return $row['lang_string']; }
Это работает отлично, но я обеспокоен тем, что может быть много запросов к базе данных. например, в главном меню имеется 5 текстов ссылок, все из которых вызывают эту функцию.
Было бы быстрее загрузить все результаты таблицы language_strings для выбранного lang_id в массив PHP, а затем вызвать это из функции? Потенциально это было бы огромным массивом с большей частью избыточным, но, очевидно, это был бы один запрос к базе данных за pageload вместо лотов.
Может ли кто-нибудь предложить другой более эффективный способ сделать это?
Нет ответа, который не чувствителен к регистру. Вы действительно можете посмотреть на него в случае отдельного случая. Сказав, что в большинстве случаев, будет быстрее получить все данные в одном запросе, поместить его в массив или объект и обратиться к нему оттуда.
Предостережение заключается в том, можете ли вы вытащить все ваши данные, которые вам нужны, в одном запросе так же быстро, как запустить пять отдельных. Именно здесь вступает в действие производительность самого запроса.
Иногда запрос, содержащий подзапрос или два, будет фактически менее эффективным, чем выполнение нескольких запросов в отдельности.
Мое предложение – проверить это. Получите запрос вместе, который получит все необходимые данные, посмотрите, сколько времени потребуется на выполнение. Время каждого из пяти других запросов и посмотреть, сколько времени они принимают вместе. Если он почти идентичен, вставьте вывод в массив, и это будет более эффективно из-за того, что вам не придется часто подключаться к самой базе данных.
Если, однако, ваш комбинированный запрос занимает больше времени для возврата данных (это может привести к полному сканированию таблицы вместо использования индексов, например), то придерживаться отдельных.
Наконец, если вы собираетесь использовать одни и те же данные снова и снова – массив или объект будут каждый раз выигрывать руки, поскольку доступ к нему будет намного быстрее, чем получение его из базы данных.
Согласитесь с тем, что все говорят здесь. Все дело в цифрах.
Некоторые дополнительные советы:
Попробуйте создать единый массив памяти, который имеет минимальный требуемый уровень. Это означает устранение большинства очевидных увольнений.
Существуют стандартные подходы к этим проблемам в критически важных средах, таких как использование memcached с mysql. Это немного перебор, но это в основном позволяет вам выделять некоторую внешнюю память и кэшировать ваши запросы там. Поскольку вы выбираете, сколько памяти вы хотите выделить, вы можете планировать ее в зависимости от того, сколько памяти у вашей системы.
Просто играйте с цифрами. Попробуйте использовать отдельные запросы (это самый простой подход) и подчеркните свой PHP-скрипт (например, вызывайте его сотни раз из командной строки). Измерьте, сколько времени это занимает, и посмотрите, насколько велика потеря производительности на самом деле. Говоря из моего личного опыта, я обычно кэширую все в памяти, а затем в один прекрасный день, когда данные становятся слишком большими, у меня заканчивается память. Затем я разбил все, чтобы отделить запросы, чтобы сохранить память, и увидеть, что влияние производительности было не так уж плохо в первую очередь 🙂
Хорошо. Я сделал некоторые бенчмаркинга и с удивлением обнаружил, что помещение вещей в массив, а не использование индивидуальных запросов, было в среднем 10-15% SLOWER.
Я думаю, причина в том, что, даже если я отфильтровывал «необычные» элементы, неизбежно всегда были неиспользуемые элементы, как само собой разумеющееся.
С индивидуальными запросами я получаю только то, что мне нужно, и поскольку запросы настолько просты, что я лучше всего придерживаюсь этого метода.
Это работает для меня, конечно, в других ситуациях, когда отдельные запросы сложнее, я думаю, что метод хранения общих данных в массиве окажется более эффективным.
Я нахожусь с Fluffeh на этом: рассмотрите другие варианты в вашем распоряжении (объединения, подзапросы, убедитесь, что ваши индексы отражают относительность данных, но не над индексом и тестом ). Скорее всего, в какой-то момент у вас получится массив, так что вот небольшой пример производительности, вопреки тому, что вы ожидаете,
$all = $stmt->fetchAll(PDO::FETCH_ASSOC);
меньше сравнивается с памятью:
$all = array();//or $all = []; in php 5.4 while($row = $stmt->fetch(PDO::FETCH_ASSOC); { $all[] = $row['lang_string ']; }
Более того: вы можете проверять избыточные данные и получать данные.
Мой ответ – сделать что-то среднее между ними. Извлеките все строки для lang_id, которые короче определенной длины (скажем, 100 символов). Более короткие текстовые строки, скорее всего, будут использоваться в нескольких местах, чем более длинные. Загрузите записи в статическом ассоциативном массиве в get_lang_string (). Если элемент не найден, загрузите его с помощью запроса.
В настоящее время я нахожусь в точке моего site/application
где мне пришлось поставить тормоза и очень внимательно следить за скоростью. Я думаю, что упомянутые упомянутые тесты скорости должны учитывать объем трафика на вашем сервере как важную переменную, которая будет влиять на результаты. Если вы помещаете данные в структуры данных javascript и обрабатываете их на клиентской машине, время обработки должно быть более регулярным. Если вы запрашиваете много данных через mysql через php (например), это ставит спрос на один компьютер / сервер, а не распространяется на него. По мере роста вашего трафика вам приходится делиться ресурсами сервера со многими пользователями, и я думаю, что именно здесь, когда JavaScript делает больше, это облегчит нагрузку на сервер. Вы также можете хранить данные на локальном компьютере через localstorage.setItem(); / localstorage.getItem();
localstorage.setItem(); / localstorage.getItem();
(у большинства браузеров около 5 мб места на домен). Если у вас есть данные в базе данных, которые не так часто меняются, вы можете сохранить их клиенту, а затем просто проверить на «запуск», если он все еще в дате / действителен.
Это мой первый комментарий, опубликованный после использования и использования учетной записи в течение 1 года, поэтому мне, возможно, потребуется тонкая настройка моего бессвязного звонка – просто озвучивая то, о чем я думаю в настоящее время.