Пропустить

Оптимизация SQL-запросов

Вопросы без привязки к версии. Установлена авточистка (2 года).
Свернуть Развернуть Правила форума Местная Конституция | Шаблон запроса | Документация (phpBB3) | Переход на 3.0.6 и выше | FAQ-3 (phpbb3) | Как задавать вопросы | Как устанавливать моды

Ваш вопрос может быть удален без объяснения причин, если на него есть ответы по приведённым ссылкам (а вы рискуете получить предупреждение ;) ).

Оптимизация SQL-запросов

Сообщение Jovani » 31.12.2004 19:49

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

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

1. отложенная запись
Очень тяжелой операцией является создание индекса в больших таблицах.
Поэтому, некоторые некритические INSERT-ы заменил INSERT DELAYED.
Это касается заполнение "поисковых" таблиц, счетчиков просмотра тем, кол-ва сообщений участника, и некоторых других.
Не знаю, как у других, но у меня, если сервер загружен, то очень большая вероятность, пойти ему в "разнос" из-за нехватки памяти.
Отложенная запись, не уменьшит количество запросов, но распределит загрузку MySQL более равномерно.
С модификацией справится любой.
Возьмем к примеру functions_search.php
Находим запросы:
$sql = "INSERT IGNORE INTO " . SEARCH_WORD_TABLE

Меняем на:
$sql = "INSERT DELAYED IGNORE INTO " . SEARCH_WORD_TABLE

Аналогично, можно отложить другие запросы в других файлах.
Идея, думаю понятна.
Естественно, это изменение очень важно для больших форумов.
В мелких форумах, нет смысла ...
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Xpert » 01.01.2005 11:45

А кто что скажет насчет применения параметра LOW PRIORITY?
Например:
INSERT LOW_PRIORITY INTO forums_topics_watch (user_id, topic_id, notify_status) VALUES
Эксперт - это человек, который избегает мелких ошибок на пути к грандиозному провалу.
Любая более-менее сложная задача имеет несколько простых, изящных, лёгких для понимания неправильных решений
Аватара пользователя
Xpert
phpBB Guru
phpBB Guru
 
Сообщения: 5492
Зарегистрирован: 13.03.2004 22:27
Откуда: msk.ru
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Jovani » 01.01.2005 14:39

Пожалуй, самое важное, при оптимизации, контролировать свои результаты.
То есть, наблюдать за выполнением SQL-запросов движка.
Мне удалось найти несколько способов, как это сделать.
При возможности, я их все, перечислю.

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

Предлагаю, для отладки запросов в базу, использовать небольшую модернизацию функции sql_query, которая позволит смотреть все SQL-запросы, время выполнения, использование индексов, и тд.
Естественно, делать это нужно не на работающем сайте, а на копии.

Открываем файл db/mysql4.php
Находим:
	function sql_query($query = "", $transaction = FALSE)
	{
		//
		// Remove any pre-existing queries
		//
		unset($this->query_result);

		if( $query != "" )
		{
			$this->num_queries++;
			if( $transaction == BEGIN_TRANSACTION && !$this->in_transaction )
			{
				$result = mysql_query("BEGIN", $this->db_connect_id);
				if(!$result)
				{
					return false;
				}
				$this->in_transaction = TRUE;
			}

			$this->query_result = mysql_query($query, $this->db_connect_id);
		}
		else
		{
			if( $transaction == END_TRANSACTION && $this->in_transaction )
			{
				$result = mysql_query("COMMIT", $this->db_connect_id);
			}
		}

		if( $this->query_result )
		{
			unset($this->row[$this->query_result]);
			unset($this->rowset[$this->query_result]);

			if( $transaction == END_TRANSACTION && $this->in_transaction )
			{
				$this->in_transaction = FALSE;

				if ( !mysql_query("COMMIT", $this->db_connect_id) )
				{
					mysql_query("ROLLBACK", $this->db_connect_id);
					return false;
				}
			}
			
			return $this->query_result;
		}
		else
		{
			if( $this->in_transaction )
			{
				mysql_query("ROLLBACK", $this->db_connect_id);
				$this->in_transaction = FALSE;
			}
			return false;
		}
	}


Меняем на:
	function sql_query($query = "", $transaction = FALSE) 
        { 
                // 
                // Remove any pre-existing queries 
                // 

                unset($this->query_result); 

                if( $query != "" ) 
                { 
                        $this->num_queries++; 

                        $this->evil .= "Start Query #" . $this->num_queries . "<br />\n" . htmlentities($query) . "<br />\n"; 
                        if(strtoupper(substr($query, 0, 6)) == "SELECT") 
                        { 
                                $x = mysql_query("EXPLAIN $query", $this->db_connect_id); 
                                $z = array(); 

                                $this->evil .= "<table><tr><th>Table</th><th>Type</th> <th>Possible</th><th>Used</th> <th>Len</th><th>Ref</th> <th>Rows</th><th>Extra</th></tr>"; 
                                while($y = mysql_fetch_array($x, MYSQL_ASSOC)) 
                                { 
                                        $this->evil .= "<tr><td>" . $y['table'] . "</td><td>" . $y['type'] . "</td><td>" . $y['possible_keys'] . "</td><td>" . $y['key'] . "</td><td>" . $y['key_len'] . "</td><td>" . $y['ref'] . "</td><td>" . $y['rows'] . "</td><td>" . $y['Extra'] . "</td></tr>"; 
                                } 
                                $this->evil .= "</table>"; 

                                $this->evil .= print_r($z, true); 
                                mysql_free_result($x); 
                        } 
                        $start = microtime(); 

                        if( $transaction == BEGIN_TRANSACTION && !$this->in_transaction ) 
                        { 
                                $result = mysql_query("BEGIN", $this->db_connect_id); 
                                if(!$result) 
                                { 
                                        return false; 
                                } 
  
                               $this->in_transaction = TRUE; 
                        } 

                        $this->query_result = mysql_query($query, $this->db_connect_id); 

                        $end = microtime(); 
                        $this->evil .= "Time Taken = " . ($end - $start) . "<br /><br />\n"; 

                } 
                else 
                { 
                        if( $transaction == END_TRANSACTION && $this->in_transaction ) 
                        { 
                                $result = mysql_query("COMMIT", $this->db_connect_id); 

			}
		}

		if( $this->query_result )
		{
			unset($this->row[$this->query_result]);
			unset($this->rowset[$this->query_result]);

			if( $transaction == END_TRANSACTION && $this->in_transaction )
			{
				$this->in_transaction = FALSE;

				if ( !mysql_query("COMMIT", $this->db_connect_id) )
				{
					mysql_query("ROLLBACK", $this->db_connect_id);
					return false;
				}
			}
			
			return $this->query_result;
		}
		else
		{
			if( $this->in_transaction )
			{
				mysql_query("ROLLBACK", $this->db_connect_id);
				$this->in_transaction = FALSE;
			}
			return false;
		}
	}



Открываем includes/page_tail.php
Находим:
'ADMIN_LINK' => $admin_link)


Меняем на:
'ADMIN_LINK' => $admin_link, 
'DB_SPEED' => $db->evil) 



Открываем overall_footer.tpl
Находим:
</body>


Меняем на:
{DB_SPEED}
</body>


Все.
Запускаем.
Теперь мы видим на странице, все выполненные запросы, и можем попытаться облегчить наиболее сложные.

Приведу пример, как с помощью вышеуказанного "отладчика" можно выловить неудачные запросы.
Возьмем к примеру, Attachment Mod от Acyd Burn.
Есть один странный запрос при просмотре темы.

Вот EXPLAIN в запросе темы с одним атачем:
SELECT a.post_id, d.* FROM phpbb_attachments a, phpbb_attachments_desc d WHERE a.post_id IN (256383) AND a.attach_id = d.attach_id ORDER BY d.filetime ASC

Возвращает:
Rows_sent: 1
Rows_examined: 4163
Possible: attach_id_post_id,attach_id_privmsgs_id
Used: attach_id_post_id
Extra: where used; Using index; Using temporary; Using filesort
Time Taken = 0.018864

Самый медленный у меня запрос при просмотре темы !
Сканирует все записи из таблицы атачей :( :(
Причем, есть индекс attach_id, post_id
Но в запросе, последовательность post_id > attach_id
Получается, индекс не используется? Хотя пишет, что используется ...
Проверяю.
Удаляю индекс attach_id_post_id

Создаю новый индекс:
CREATE INDEX post_id_attach_id ON phpbb_attachments (post_id, attach_id);
То есть, с другой последовательноcтью.

Делаю EXPLAIN:
Rows_sent: 1
Rows_examined: 1
Possible: attach_id_privmsgs_id,post_id_attach_id
Used: post_id_attach_id
Extra: where used; Using index; Using temporary; Using filesort
Time Taken = 0.002231

Вот так.
Теперь, видно, что индекс используется.
Скорость выборки увеличена почти в 10 раз.
Думаю, что при большом количестве атачей, разница в скорости была бы еще больше.
Последний раз редактировалось Jovani 06.01.2005 21:34, всего редактировалось 1 раз.
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Xpert » 04.01.2005 11:33

Jovani
Я только обрадовался, что тут хорошая тема появилась... нужная... начал искать кто из моих знакомых держит большие форумы... и вот те на... :cry:
Эксперт - это человек, который избегает мелких ошибок на пути к грандиозному провалу.
Любая более-менее сложная задача имеет несколько простых, изящных, лёгких для понимания неправильных решений
Аватара пользователя
Xpert
phpBB Guru
phpBB Guru
 
Сообщения: 5492
Зарегистрирован: 13.03.2004 22:27
Откуда: msk.ru
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Re: Оптимизация SQL-запросов

Сообщение romutis » 04.01.2005 12:57

Jovani писал(а):1. отложенная запись
Очень тяжелой операцией является создание индекса в больших таблицах.
Поэтому, некоторые некритические INSERT-ы заменил INSERT DELAYED.

...

Естественно, это изменение очень важно для больших форумов.
В мелких форумах, нет смысла ...


Отложенный INSERT не всегда спасает. Пример - вставка в поисковую таблицу производится каждую секунду (в форуме пишется 1 сообщение в 10 секунд - ну и сообщения состоят явно не из одного слова). Такому INSERTу просто некуда "откладываться". Ждать 12-18 часов до ночного снижения активности посетителей?

Мне кажется, что правильная конфигурация my.cnf в этом случае даст гораздо больший выигрыш в производительности.
// romutis

romutis
phpBB 2.0.0
 
Сообщения: 111
Зарегистрирован: 09.06.2004 8:00
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Jovani » 04.01.2005 17:00

Мне кажется, что правильная конфигурация my.cnf в этом случае даст гораздо больший выигрыш

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

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение romutis » 04.01.2005 17:18

Jovani писал(а):Это так, только многие даже не знают, о существовании такого файла, и доступ к нему, есть далеко не у всех.
Поэтому я пытался рассматривать доступные варианты.
Но гуру, как всегда, отмалчивается, поэтому не вижу для себя смысла продолжать эту тему здесь.
Вот когда вас хостер "попросит" снизить нагрузку, тогда вы возможно вспомните про эту тему.


Немного странно звучит - "большой форум" и отсутсвие настройки под себя параметров БД. Или мы под словом "большой форум" понимаем разные вещи? ИМХО, "большой форум" - это форум, зарегистрированный в списках на www.big-boards.com - для того, чтобы менеджить форумы такого размера и активности, админы явно должны иметь знания выше, чем суметь установить phpBB.
// romutis

romutis
phpBB 2.0.0
 
Сообщения: 111
Зарегистрирован: 09.06.2004 8:00
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Jovani » 04.01.2005 17:23

romutis
Большой, маленький - это понятия относительные.
Под большим, я подразумеваю форум, где как правило более сотни в онлайн.
Для того, чтобы сделать большой форум, не обязательно иметь семь пядей во лбу. Достаточно просто хорошо провести политику раскрутки.
Ну а тут - http://www.big-boards.com вообще гиганты.
При создании темы, я надеялся собрать некоторые мысли, как выжить большому форуму на shared-хостинге, например облегчив и убрав некоторые SQL-запросы.
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение romutis » 04.01.2005 17:36

Jovani писал(а):romutis
Большой, маленький - это понятия относительные.
Под большим, я подразумеваю форум, где как правило более сотни в онлайн.
Для того, чтобы сделать большой форум, не обязательно иметь семь пядей во лбу. Достаточно просто хорошо провести политику раскрутки.
Ну ат тут - http://www.big-boards.com вообще гиганты.


Много ты знаешь народа с этого форума, у которых стабильно сотня посетителей в онлайне? Желательно зарегистрированных, а не "прилетевших" на 1 сек по баннерному переходу. Пиковое значение счетчика, вызванное в конце декабря атакой червя, тоже считать не надо.

Сделать большой форум "обо всем" или о порнухе / варезе всё же легче чем большой узкоспециализированный форум. Зато ценность и сплоченность комьюнити у узкоспециализированного форума не в пример выше.


P.S. на big-boards.com - не гиганты, а просто форумы, просуществовавшие 2-3 года и имеющие интересный для посетителя контент.

Добавлено спустя 2 минуты 50 секунд:

Jovani писал(а):При создании темы, я надеялся собрать некоторые мысли, как выжить большому форуму на shared-хостинге


Опа. Пропустил эту мысль про shared-hosting.
Ладно, тогда пойду я из этой темы - нечего мне особо про shared-hosting сказать, мало знаком с phpBB на shared-хостинге... :(
// romutis

romutis
phpBB 2.0.0
 
Сообщения: 111
Зарегистрирован: 09.06.2004 8:00
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Mr. Anderson » 04.01.2005 17:41

romutis
Скажите о том хостинге, о котором имеете представление - это нелишним будет.
Jovani
Собственно только ответь хотел... Особенно по поводу PostgreSQL, а вы...
Верните, плиз!!!
Правила конференции (30.05.2011) | Общие ошибки новичков (07.11.2005) | Шаблон запроса | FAQ (phpBB 3.0.x)
Последняя и единственно актуальная на сегодня версия - 3.0.10!
Поддержка по ICQ, e-mail и ЛС оказывается только за WM!


phpBB Guru blog
Аватара пользователя
Mr. Anderson
phpBB Guru
phpBB Guru
 
Сообщения: 5431
Зарегистрирован: 13.03.2004 22:32
Откуда: СССР
Благодарил (а): 5 раз.
Поблагодарили: 86 раз.

Сообщение Jovani » 04.01.2005 17:57

А про shared-хостинг, можно очень даже интересные вещи сказать ...
Например, когда сервер начинает ложиться, админ сервера, как положено смотрит Top Process.
И считайте, что вам не повезло, если вы оказались в этом списке.
Так вот, есть идеи, как не попасть в этот список :)
То есть, тяжелые процессы разбить на несколько мелких. Но это несколько другая тема ...

Собственно только ответь хотел... Особенно по поводу PostgreSQL

Пока сказать нечего, я не знаком с PostgreSQL.
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Mr. Anderson » 04.01.2005 18:12

Jovani
Пока сказать нечего, я не знаком с PostgreSQL

Полагаю поэтому вы и спрашивали... Так вот повторите вопрос :)
Правила конференции (30.05.2011) | Общие ошибки новичков (07.11.2005) | Шаблон запроса | FAQ (phpBB 3.0.x)
Последняя и единственно актуальная на сегодня версия - 3.0.10!
Поддержка по ICQ, e-mail и ЛС оказывается только за WM!


phpBB Guru blog
Аватара пользователя
Mr. Anderson
phpBB Guru
phpBB Guru
 
Сообщения: 5431
Зарегистрирован: 13.03.2004 22:32
Откуда: СССР
Благодарил (а): 5 раз.
Поблагодарили: 86 раз.

Сообщение Jovani » 04.01.2005 18:39

Так вот повторите вопрос

В принципе, меня интересовала оправданность перевода большого форума на PostgreSQL.
То есть, чего можно ожидать как хорошего, так и плохого.
Интересует больше, не теория, а практические результаты тех, кто ЭТО делал.
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

Сообщение Mr. Anderson » 04.01.2005 18:53

Jovani
Рассказываю - постгрес больше "любит" бОльшее кол-во запросов в единицу вермени.
Делать запрос хранимой процедурой в посгресе не имеет практического смысла так как обработка процедуры займет определенное (и далеко не маленькое) время (это если запросов много).
Правила конференции (30.05.2011) | Общие ошибки новичков (07.11.2005) | Шаблон запроса | FAQ (phpBB 3.0.x)
Последняя и единственно актуальная на сегодня версия - 3.0.10!
Поддержка по ICQ, e-mail и ЛС оказывается только за WM!


phpBB Guru blog
Аватара пользователя
Mr. Anderson
phpBB Guru
phpBB Guru
 
Сообщения: 5431
Зарегистрирован: 13.03.2004 22:32
Откуда: СССР
Благодарил (а): 5 раз.
Поблагодарили: 86 раз.

Сообщение Jovani » 04.01.2005 19:15

Это все теория.
Я уже не раз, убеждался, что теория, не всегда соответствет практике.
Вернее соответствует, только, на практике выясняется, что в чей-то теории, не были учтены некоторые моменты.
И это, всегда идет как-бы "оправданием".
Поэтому, в первую очередь, я всегда стараюсь на практике, проверить результат.

А в переводе phpBB на PostgreSQL меня интересует именно практический результат.
Я сейчас полностью передаю свой форум новому админу, и хочу что-бы еще несколько лет не возникало бы проблемы с движком, из-за увеличения в потреблении ресурсов, пока он не разберется досканально со всеми тонкостями.

В общем, меня, в данный момент интересут практика, которую я хотел бы услышать от Гуру.


PS.
Но увы :(
Похоже, что Гуру более интересуют темы - Не отображается страница http://localhost/forum
Уже три страницы идет обсуждение этого вопроса, вместо того, чтобы заставить ленивого, ОДИН раз, внимательно, прочитать инструкцию.
Всегда есть решение ...

Jovani
phpBB 2.0.15
 
Сообщения: 496
Зарегистрирован: 28.04.2004 2:56
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.

След.

Вернуться в phpBB-пространство

 

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

Бессрочный конкурс phpBB-ориентированных материалов
FastVPS — надёжный и доступный хостинг для phpBB
Изображение