Возьмем это за идеализированную модель.
Конечно, когда сайт уже относительно статичен, в теории можно сделать супер-запрос, который бы заполнял супер-класс, а потом из этого класса брались бы данные. Но на практике такие решения не встречаются из-за своей, мягко говоря, негибкости.
Итак, вопрос к знатокам: Существуют ли решения, максимально близкие к идеализированной модели, но в тоже время обладающие хоть какой-то гибкостью.
Спустя 53 минуты, 15 секунд (30.04.2010 - 12:46) sergeiss написал(а):
Цитата (b00tanik @ 30.04.2010 - 12:53) |
в теории можно сделать супер-запрос, который бы заполнял супер-класс, а потом из этого класса брались бы данные. |
То есть, ты хочешь получить все данные из БД? Только не говори, что это не так

А вот представь, что у тебя 200 ГБ (Двести Гига Байт) данных, и то, не считая индексов. И чё? Ты их будешь грузить в скрипт? А нафига тогда вообще было создано такое понятие, как БД и всякие запросы к ней?
Спустя 1 час, 1 минута, 10 секунд (30.04.2010 - 13:47) Gabriel написал(а):
b00tanik
не всегда один запрос к БД будет быстрее 2. оптимизировать есть смысл только в том случае, когда ты уверен, что получишь те-же данные с меньшей затратой времени и ресурсов, а если это не так то это получится ДЕоптимизация какая-то которая в свою очередь не нужна не программеру ни юзеру, ни серверу.
не всегда один запрос к БД будет быстрее 2. оптимизировать есть смысл только в том случае, когда ты уверен, что получишь те-же данные с меньшей затратой времени и ресурсов, а если это не так то это получится ДЕоптимизация какая-то которая в свою очередь не нужна не программеру ни юзеру, ни серверу.
Спустя 3 часа, 45 минут, 2 секунды (30.04.2010 - 17:32) b00tanik написал(а):
Цитата (sergeiss @ 30.04.2010 - 09:46) |
То есть, ты хочешь получить все данные из БД? Только не говори, что это не так ![]() |
Это не так:) Я хочу получить из БД только те данные, которые мне нужны для данной страницы. Одним большим запросом, с вложенными селектами и тд.
В этом и состоит сложность - чтобы оптимизировать на получение только нужных данных а не всех.
ЗЫ: 200 Гб таскать мускулем? Знаете толк в извращениях. Для таких объемов уже свои решения, таже касандра например.
Тут скорее разговор идет об отдаче небольших объемов, раскиданных по базе и очень часто.
Цитата (Gabriel @ 30.04.2010 - 09:46) |
не всегда один запрос к БД будет быстрее 2 |
Были ли исследования по данному вопросу или это из личного опыта. Если из опыта, то можете в паре слов описать, когда выгодней 2 запроса.
Спустя 24 минуты, 26 секунд (30.04.2010 - 17:57) FatCat написал(а):
Цитата (b00tanik @ 30.04.2010 - 18:32) |
Если из опыта, то можете в паре слов описать, когда выгодней 2 запроса. |
Пример из реальной практики движка этого форума.
При отображении списка тем форума требуется пометить темы, содержащие сообщения того, кто просматривает страницу.
Если заджойнить к таблице топиков таблицу постов, можно получить все данные в один запрос, время выполнения примерно 0.05 секунды.
Если забрать только таблицу топиков и в цикле по топикам гонять запросы к таблице постов, получается 51 запрос, но суммарное время этих запросов меньше 0.01 секунды.
Спустя 6 минут, 2 секунды (30.04.2010 - 18:03) FatCat написал(а):
Кстати, у MySQL есть свои средства оптимизации запросов. Нужно только воспользоваться.
При коннекте получить идентификатор соединения, например так:
При отправке запросов, отправлять их в том же идентификаторе:
И в конце закрывать соединение:
При коннекте получить идентификатор соединения, например так:
$this->connection_id = mysql_connect(...);
При отправке запросов, отправлять их в том же идентификаторе:
$this->query = mysql_query($the_query, $this->connection_id);
И в конце закрывать соединение:
mysql_close($this->connection_id);
Спустя 9 минут, 29 секунд (30.04.2010 - 18:12) vasa_c написал(а):
А если не указывать connection_id, запросы будут отправляться в каком-то другом идентификаторе?
Спустя 43 минуты, 5 секунд (30.04.2010 - 18:55) sergeiss написал(а):
Цитата (b00tanik @ 30.04.2010 - 18:32) |
ЗЫ: 200 Гб таскать мускулем? Знаете толк в извращениях. |
Я как раз по столько не таскаю

Я выбираю только те данные, что мне нужны. Вот только фенька в том, что в начале страницы может быть неизвестно, что же именно надо будет вытащить! Это определяется в процессе обработки данных. В зависимости от каких-то условий подключаются те или иные скрипты, в которых могут делаться еще какие-то выборки.
Поэтому я и говорю, что либо данные будут выбираться по мере необходимости в несколько запросов, либо надо загрузить всё, и уже в ПХП-скрипте выбирать, что же нужно.
И еще - скорость выполнения запросов (в первую очередь для сложных запросов) зависит также и от того, насколько правильно прописаны индексы. И насколько правильно построен сам сложный запрос. Разница может быть в десятки-сотни-тысячи раз.
Спустя 4 часа, 19 минут, 4 секунды (30.04.2010 - 23:15) kirik написал(а):
b00tanik
Уменьшение количества запросов не есть оптимизация. Запрос отправляется серверу БД за доли долей секунды, а вот процесс выборки уже может происходить довольно продолжительное время. Именно по этому появляются "too many connections" - 100 сложных запросов пришли, сервер их отрабатывает, а 101-й запрос уже взять не может.
Уменьшение количества запросов не есть оптимизация. Запрос отправляется серверу БД за доли долей секунды, а вот процесс выборки уже может происходить довольно продолжительное время. Именно по этому появляются "too many connections" - 100 сложных запросов пришли, сервер их отрабатывает, а 101-й запрос уже взять не может.
Спустя 22 минуты, 19 секунд (30.04.2010 - 23:37) FatCat написал(а):
Цитата (vasa_c @ 30.04.2010 - 19:12) |
если не указывать connection_id, запросы будут отправляться в каком-то другом идентификаторе? |
Не знаю.
Была ситуация, когда чат валил sql-сервер в перезагрузки. Переписал движок чата, посадил все запросы на один connection_id, падения прекратились. Может совпало, другого опыта не было.
Спустя 18 часов, 41 минута, 50 секунд (1.05.2010 - 18:19) Nikitian написал(а):
Цитата (FatCat @ 30.04.2010 - 20:37) |
Может совпало, другого опыта не было. |
Совпало. Если не указывать явно идентификатор соединения, то будет использоваться последний использованный (:
Цитата |
Именно по этому появляются "too many connections" - 100 сложных запросов пришли, сервер их отрабатывает, а 101-й запрос уже взять не может. |
Не так. Too many connections появляется, когда количество одновременных соединений с бд превышает параметр max_connections. Из доков. Именно поэтому всем советую коннектиться к бд не в самом начале скрипта, а когда это действительно нужно. Mysql_connect в __construct() не есть гуд, как и игнорирование mysql_close(). А уж если wait_timeout и connect_timeout имеют большое значение, то too many connections долго ждать не приходится - очень неприятная ошибка, т.к. появляется неожиданно, когда в раскрутку начинают вкладываться, соответственно деньги просто вылетают в трубу.
Спустя 3 часа, 46 минут, 49 секунд (1.05.2010 - 22:05) FatCat написал(а):
Цитата (Nikitian @ 1.05.2010 - 19:19) |
Если не указывать явно идентификатор соединения, то будет использоваться последний использованный (: |
А если у меня одновременно сотни посетителей? обычная нагрузка в вечернее время составляет 2500 генераций страниц в минуту; это больше 40 в секунду.
Мне кажется, что запросы от разных генераций страниц разными посетителями будут или пересекаться, или сваливаться в один айдишник.
Цитата (Nikitian @ 1.05.2010 - 19:19) |
Too many connections появляется, когда количество одновременных соединений с бд превышает параметр max_connections. |
Ни разу не видел такого от MySQL, нверное с хостерами везло, но и сам не усердствовал в "оптмизациях". Если в апаче не переусердствовать, то он первым даст отлуп, не заваливая MySQL-сервер.
Спустя 3 часа, 55 минут, 53 секунды (2.05.2010 - 02:01) Nikitian написал(а):
Цитата (FatCat @ 1.05.2010 - 19:05) |
А если у меня одновременно сотни посетителей? обычная нагрузка в вечернее время составляет 2500 генераций страниц в минуту; это больше 40 в секунду. Мне кажется, что запросы от разных генераций страниц разными посетителями будут или пересекаться, или сваливаться в один айдишник. |
Вам кажется. Такое ощущение, что вы от пятницы ещё не отошли )) Идентификатор запроса - это ресурс, а не какой-то псевдослучайный числовой идентификатор. Он не повторяется, т.к. выдаётся конкретному потоку веб-сервера b убивается сборщиком мусора. Повторяться он не может, т.к. выдаётся в рамках вебсервера и в этих рамках он уникален независимо от количества одновременных потоков. Если мне не изменяет память (а она у меня верная), после отправки запроса к серверу бд не происходит разрыва соединения, а оно висит, пока не будут возвращены данные. Отсюда очевидно, что пересекаться там нечему. Если же соединение с клиентом потеряно, то результат запроса не передаётся никуда вообще. Не может быть такой ситуации, что один отправил запрос и отвалился, а другой подключился и принял ответ - вновь подключённый будет новым клиентом для бд, даже если это тот же поток и скрипт подключается снова. Единственное, что не могу объяснить: как связка: php-mysql будет себя вести на одновременных запросах одного скрипта при использовании одновременных потоков и одного соединения с бд, но уверен, что там всё схвачено )
Цитата (FatCat @ 1.05.2010 - 19:05) |
Ни разу не видел такого от MySQL, нверное с хостерами везло, но и сам не усердствовал в "оптмизациях". Если в апаче не переусердствовать, то он первым даст отлуп, не заваливая MySQL-сервер. |
Увеличиваете указанные ранее параметры, уменьшаете max_connections и вуаля.
Цитата |
Получение ошибки Too many connections при попытке соединиться с MySQL означает, что уже есть max_connections клиентов, соединившихся с сервером mysqld. |
Спустя 12 часов, 10 секунд (2.05.2010 - 14:02) FatCat написал(а):
Цитата (Nikitian @ 2.05.2010 - 03:01) |
Единственное, что не могу объяснить: как связка: php-mysql будет себя вести на одновременных запросах одного скрипта при использовании одновременных потоков и одного соединения с бд, но уверен, что там всё схвачено ) |
Когда разбирались с обвалами SQL-сервера, логировали его работу в файл.
Файл был такого вида:
[99]SELECT .....В квадратных скобках - идентификатор сессии.
[91]SELECT.....
[97]SELECT.....
[99]SELECT .....
Я еще программку писал для разбора этих логов, чтобы посмотреть последовательность запросов именно той сессии, на которой произошло падение сервера, и посмотреть прошлые запросы в этой сессии.
Оказалось, что в самих запросах не было ничего криминального, падения происходили при накоплении сессий, не завершившихся командой mysql_close
Спустя 35 минут, 27 секунд (2.05.2010 - 14:37) Nikitian написал(а):
mysql_close() разумеется обязателен, несмотря на допущения в его неиспользовании из доков. Причём завершать соединение надо не в конце скрипта, а когда бд уже не требуется, но есть ещё чем занять скрипт Например, самый подходящий момент - перед генерацией шаблонизатором.
Спустя 6 часов, 50 минут, 40 секунд (2.05.2010 - 21:28) kirik написал(а):
Цитата (Nikitian @ 1.05.2010 - 10:19) |
Не так. Too many connections появляется, когда количество одновременных соединений с бд превышает параметр max_connections. Из доков. |
Эмм.. Я как-то по-другому сказал?

Спустя 1 час, 14 минут, 13 секунд (2.05.2010 - 22:42) Nikitian написал(а):
kirik
Разница в том, что мускуль может и не выполнять никаких действий. С ним просто соединились, но запросы не шлют. Я к тому веду, что делать в начале скрипта mysql_connect(), и забывать или делать в конце mysql_close() - не самый правильный шаг. Например из базы дёргаются какие-то данные, которые потом курлом шлются во внешку, а таймаут соединения стоит скажем 20 секунд. Внешний сервер отвалился, курл терпеливо ждёт 20 секунд и потом возвращает ошибку, но все эти 20 секунд мускуль так же ждал запросов и -1 соединение держал, хотя после отправки данных мускуль нам был уже не нужен. Т.е. если за 20 секунд открыли 100 страниц, а это всего лишь 5 страниц в секунду, то всем остальным показали "Mysql not connected". И заметьте, здесь не делалось тяжёлых запросов в бд, не было сверх-посещаемости
Разница в том, что мускуль может и не выполнять никаких действий. С ним просто соединились, но запросы не шлют. Я к тому веду, что делать в начале скрипта mysql_connect(), и забывать или делать в конце mysql_close() - не самый правильный шаг. Например из базы дёргаются какие-то данные, которые потом курлом шлются во внешку, а таймаут соединения стоит скажем 20 секунд. Внешний сервер отвалился, курл терпеливо ждёт 20 секунд и потом возвращает ошибку, но все эти 20 секунд мускуль так же ждал запросов и -1 соединение держал, хотя после отправки данных мускуль нам был уже не нужен. Т.е. если за 20 секунд открыли 100 страниц, а это всего лишь 5 страниц в секунду, то всем остальным показали "Mysql not connected". И заметьте, здесь не делалось тяжёлых запросов в бд, не было сверх-посещаемости

Спустя 29 минут, 17 секунд (2.05.2010 - 23:11) kirik написал(а):
Nikitian
Окей, если "too many connections" привязана только к превышению значения max_connections, то как можно объяснить подобный случай?
Есть сайт (соцсеть), онлайн где-то 500-700 человек постоянный. Так вот, стала частенько вылетать ошибка "too many connections". Глянул "лог медленных запросов" - некоторые выполнялись аж под 30 секунд! Решено было прикрутить мемкэш - прикрутили, ошибка стала появляться намного реже. mysql_connect никуда не девался, директиву max_connections не изменяли (да и вообще настройки mysql не трогали). Когда онлайн поднялся до 900 человек, опять повалили "too many connections".. Тогда уже решили попробовать расширить память на 1ГБ и соответственно выделить mysql'у побольше. Так ошибка пропала, и теперь появляется очень редко.
Как я предположил, вероятно это было связано с тем, что mysql не закроет соединение, пока не вернет запрос данному клиенту. Тоесть превышение количества одновременных подключений возможно не только из-за того что реально 101 юзер просто обрататся к БД одновременно..
Окей, если "too many connections" привязана только к превышению значения max_connections, то как можно объяснить подобный случай?
Есть сайт (соцсеть), онлайн где-то 500-700 человек постоянный. Так вот, стала частенько вылетать ошибка "too many connections". Глянул "лог медленных запросов" - некоторые выполнялись аж под 30 секунд! Решено было прикрутить мемкэш - прикрутили, ошибка стала появляться намного реже. mysql_connect никуда не девался, директиву max_connections не изменяли (да и вообще настройки mysql не трогали). Когда онлайн поднялся до 900 человек, опять повалили "too many connections".. Тогда уже решили попробовать расширить память на 1ГБ и соответственно выделить mysql'у побольше. Так ошибка пропала, и теперь появляется очень редко.
Как я предположил, вероятно это было связано с тем, что mysql не закроет соединение, пока не вернет запрос данному клиенту. Тоесть превышение количества одновременных подключений возможно не только из-за того что реально 101 юзер просто обрататся к БД одновременно..
Спустя 9 минут, 41 секунда (2.05.2010 - 23:21) FatCat написал(а):
Цитата (Nikitian @ 2.05.2010 - 23:42) |
Т.е. если за 20 секунд открыли 100 страниц, а это всего лишь 5 страниц в секунду |
Эм...
У меня сейчас в httpd.conf установлено
MaxClients 15- это втрое выше дефолтных "5".
Если скрипт 20 секунд ждет курла, 15 клиентов будут наблюдать страницу с ожиданием ответа, а 16-й просто получит 502-ю страницу. Или не так?
Спустя 10 минут, 16 секунд (2.05.2010 - 23:31) FatCat написал(а):
Цитата (kirik @ 3.05.2010 - 00:11) |
решили попробовать расширить память на 1ГБ и соответственно выделить mysql'у побольше |
Ох, подозреваю, что над одной проблемой маемся, только с разными ее проявлениями.
Я сейчас ковыряюсь с проблемой "холодных стартов": например, не было вообще посетителей, захожу на сайт, и... 10-15 секунд ожидания.
При этом дебагер показывает время генерации страницы php несчастные 0,03-0,05 секунды. Обновляю страницу, и получаю с теми же цифрами на дебаггере, но ответ моментально.
И время задержки "холодного старта" растет прямо пропорционально размеру одной из таблиц в БД...
Думал, что может всю таблицу считывает с харда и в оперативу грузит; проверил в локалке на денвере, вроде ни фига, таблица хорошо за сотню Мб, а прирост потребления оперативы виндой составляет всего пару мегабайт...
Спустя 20 минут, 24 секунды (2.05.2010 - 23:52) Nikitian написал(а):
Превысить max_connections можно как долбёжкой медленными запросами, так и удержанием неактивных соединений.
Цитата |
как можно объяснить подобный случай? |
500 человек онлайн - это сколько страниц в секунду? Если соцсеть, то 500 человек за 5 минут (обычно онлайнеров считают именно за это время) - это 1.5 человека в секунду. За 5 минут каждый откроет минимум 5 страниц, итого округлим до 10 страниц в секунду. Допустим одна страница - это 10 запросов. Итого 100 запросов в секунду. Отсюда видим, что был предел и любой запрос, отрабатывающий больше секунды начинал строить очередь ожидания, увеличивая очередь в геометрической прогрессии. А пропала ошибка из-за того, что мускуль быстрее стал отрабатывать ваши запросы (памяти больше -> больше таблиц в памяти помещалось -> быстрее отрабатываются запросы) и очередь не строится.
Вроде правильно посчитал.
Вообще зря не трогали настройки мускуля. Очень советую админов нагружать оптимизацией софта. Если админ ненагружаем, то как вариант, mysqltuner - интересные вещи творит.
Короче, ошибка too many connections возникает и от тяжёлых запросов, и от большого количества одновременных открытий соединений с бд.
Цитата |
Я сейчас ковыряюсь с проблемой "холодных стартов": например, не было вообще посетителей, захожу на сайт, и... 10-15 секунд ожидания. При этом дебагер показывает время генерации страницы php несчастные 0,03-0,05 секунды. |
Может это проблема днса? Либо MaxSpareServers сильно мал, а мускуль забивает всю память кэшем этой большой таблицы. Соответственно когда апачу надо запустить нового клиента часть мускульной оперативки свопится и заполняется дополнительным процессом апача и он отрабатывает именно за указанное время, ведь раньше, чем запустится дочерний процесс статистика дебаггера считаться не будет?
Цитата |
MaxClients 15Если скрипт 20 секунд ждет курла, 15 клиентов будут наблюдать страницу с ожиданием ответа, а 16-й просто получит 502-ю страницу. Или не так? |
MaxClients - параметр указывает сколько дочерних процессов можно создавать родительскому апача. Поведение будет именно таким, как вы сказали.
Спустя 1 день, 11 часов, 11 минут, 21 секунда (4.05.2010 - 11:03) b00tanik написал(а):
Решил проблему по-другому. Вот топик с новой темой