Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Высокая нагрузка на работу с БД. Посоветуйте как разгрузить. 
:(
    Опции темы
gogzor
Дата 3.3.2010, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 21.9.2006

Репутация: нет
Всего: нет



Привет всем.
Есть достаточно нагруженный сайт, меня попросили както переписать/оптимизировать код работы с бд (MySQL).
Что пришло первое в голову это создать класс по шаблону синглтон.
Т.е тогда у каждого юзера будет только 1 инстанс класса на всю сессию и 1 открытое соединение, которое обрабатывает все его запросы.

Примерно так :
Код

class DBManager {
    
    private static $instance;
    public $dblink;
    
    private function __construct(){}
    
    public static function GetInstance() {
        
        if(is_null(self::$instance)) {
            $newInstance = __CLASS__;
            self::$instance = new $newInstance;
            self::$instance->dblink = mysql_connect("host", "user", "pass");
        }
        
        return self::$instance;
    }

    ...

}



Сервер в распоряжении только один, так что возможности распределять всё по серверам нету.
Может вы ещё чтото посоветуете?

Спасибо.

PM MAIL   Вверх
Vasay
Дата 3.3.2010, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2097
Регистрация: 8.3.2006

Репутация: нет
Всего: 73



gogzor

Цитата

Что пришло первое в голову это создать класс по шаблону синглтон.
Т.е тогда у каждого юзера будет только 1 инстанс класса на всю сессию и 1 открытое соединение, которое обрабатывает все его запросы.


PHP - не C# smile Тут это работать будет по своему  -  т.к. время жизни синглтона - один запрос (а не сессия). 



Весьма радикальный вариант облегчить жизнь БД - запустить php приложение на resin (желательно коммерческой версии ) Предварительно настроив database connection pool как JNDI ресурс сервера. И переписать всю работу с бд с использованием этого JNDI.

Код


<?php

  // standard PHP
  //mysql_connect($host, $username, $password, $dbname);

  // using JNDI lookup
  mysql_connect("java:comp/env/jdbc/myDatabaseName");

?>


Тогда работа с БД будет идти через пул соединений, что при его грамотной настройке даст серьезное снижение нагрузки с сервера БД.

Это сообщение отредактировал(а) Vasay - 3.3.2010, 19:46


--------------------
Придумать идеальную защиту от дурака невозможно, дураки, наудивление, изобретательны.
PM MAIL   Вверх
gogzor
Дата 3.3.2010, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 21.9.2006

Репутация: нет
Всего: нет



Vasay, спасибо, посмотрю что это за зверь.

Ипатьев, спасибо, очень информативный ответ от юзера со статусом "эксперт".  smile 
PM MAIL   Вверх
smartov
Дата 3.3.2010, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 1
Всего: 259



gogzor, прежде чем переписывать код, надо найти узкие места.
Разобраться в чем они: тяжелые запросы? большое количетсво запросов?
Исходя из ситуации либо оптимизировать тяжелые запросы, либо структуру базы, чтобы они не были такими тяжелыми, либо консолидировать большое количество запросов в более емкий и оптимальный.
PM MAIL   Вверх
Ипатьев
Дата 3.3.2010, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2232
Регистрация: 5.7.2009

Репутация: 0
Всего: 37



Вообще, судя по формулировке задания, непонятна область ответственности топикстартера. Имеется ли у него доступ к нужной информации. 
Но сама, конечно, формулировка, многое говорит о тех, кто ставил задачу. Учитывая, что код доступа к бд никогда не бывает узким метстом.
PM MAIL   Вверх
IgorIV
Дата 3.3.2010, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 7.9.2009

Репутация: нет
Всего: 8



Цитата(gogzor @  3.3.2010,  20:07 Найти цитируемый пост)
Ипатьев, спасибо, очень информативный ответ от юзера со статусом "эксперт". 

Раз так, тогда выполняй.
Чтобы не превращать топик во флеймовый, gogzor, в твоих же интересах выдать конкретную информацию. Количество пользователей, размер базы, тяжелые запросы и остальное, в том же духе. Разобраться почему так тяжело базе. 
А пока все думают, что база для тебя черный ящик. Что там внутри ты не знаешь.
PM MAIL   Вверх
Majesty
Дата 23.7.2010, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 20.3.2005
Где: Almaty, Kazakhsta n

Репутация: нет
Всего: нет



Нужен не синглтон, а отложенная инициализация с кеширующей прослойкой. Примерно так:
Код
class DB {
    private $db_host;
    private $db_login;
    private $db_pass;
    private $db_name;
    private $db_link;
    private $cache;

    public function __construct($host, $login, $pass, $name, $cacher) {
        $this->db_host = $host;
        $this->db_login = $login;
        $this->db_pass = $pass;
        $this->db_name = $name;
        $this->cache = $cacher;
    }

    private function connect() {
        if(!is_resource($this->db_link)) {
            $this->db_link = mysql_connect($this->db_host, $this->db_login, $this->db_pass);
            mysql_select_db($this->db_name, $this->db_link);
        }
    }

    public function query($query) {
        if(false === ($result = $this->cache->read($query)) {
            $this->connect();
            $r = mysql_query($query, $this->db_link);
            while(false !== ($row = mysql_fetch_assoc($r))) {
                $result[] = $row;
            }
            $this->cache->write($query, $result);
        }
        return $result;
    }
}
Очень приблизительно так. При запросе спрашиваем в кеше, есть ли там результат такого запроса. Если нет - подключаемся, получаем результат и сохраняем в кеше. Потом результат возвращаем.

Нужно добавить парсинг запроса (чтобы не кешировать INSERT/UPDATE/DELETE запросы) и проверку на возврат false из mysql_query (хотя бы возвращать $result = false, если запрос завершился ошибкой).

Подключение к базе устанавливается только в том случае, если оно реально нужно. Один и тот же запрос выполняется однократно. Кеш можно сохранять в файлах, в sqlite, в memcached, в apc - где угодно (правильный кеш - тема, достойная отдельного топика).

Естественно, все эти телодвижения не заменяют профилирование самих запросов - slow_queries_log и explain в помощь. Если медленные запросы всё-таки нужны, следует вынести их в асинхронный режим (например, выполнять их в кроне, записывая в тот же кеш, чтобы клиенты читали результаты только из кеша). Опять же, профилирование и оптимизация запросов - это отдельная большая тема имеющая мало общего с PHP.
PM MAIL WWW   Вверх
smartov
Дата 23.7.2010, 15:04 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


свой собственный
****


Профиль
Группа: Экс. модератор
Сообщений: 4225
Регистрация: 2.2.2006
Где: NJ

Репутация: 1
Всего: 259



Majesty
1) не надо поднимать старые темы
2) когда человек спрашивает совета как правильно отрезать ухо, если у него чешется нос, то не надо подсказывать размер ножа - нужно подсказать почесать нос (на всякий случай: это аллегория)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.0717 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.