Комментарии 81
100 мегабайт кода? О_о
+7
Ну да, а в чём проблема :)? За несколько лет работы 4-7 человек можно и больше написать :). Активного кода — где-то 20 Мб
+1
Пардон, показалось сначала, что 100 мегабайт кода занял инструмент для автоматического предупреждения подобных проблем :-)
0
получается 3.75 млн строк примерно, за 4 года работы каждому кодеру из 7 человек нужно писать по 466 строк кода каждый день. учитывая выходные и праздники. дайте мне таких кодеров, которые могут 24/7 писать 500 строк нужного рабочего кода в день :) я им буду платить ооочень много
+2
Symfony — нефиговый кодогенератор, так что почему бы и нет.
+1
дык тут же человек говорит, что все руками написано :)
0
У нас проект примерно на 300МБ кода
0
Исключая внешние библиотеки?..
0
Так точно. Без Пейпала, картинок интерфейса (css, js и шаблоны будем считать за код — они же написаны вот этими мозолистыми руками :) ) и т.п.
+1
А у вас пейпал (PayPal) какой-то большой?
0
хотел бы я поглядеть на проект в 300 МБ чистого пхп кода. если в среднем одна строка занимает 80 символов, то это получается 3.75 млн строк кода. вы что амазон там написали? чтобы обслуживать такой воистину громадный проект нужен как минимум кластер. а там уже совсем другие методики оптимизации используются в дополнение к сказанному вами.
0
Ну, вот цифры для проекта, о котором шла речь:
Думайте сами :))
# количество строк
$ cat `find . | grep .php | grep -v 'cache/'` 2>/dev/null | wc -l
2066539
# количество байт
$ cat `find . | grep .php | grep -v 'cache/'` 2>/dev/null | wc -c
74121750
Думайте сами :))
0
ну тут же 75 мегабайт кода ;) а не 300. и сдается мне это со всеми библиотеками.
0
Я говорил про проект в статье :). И это один проект, а их у нас есть ещё другие, поменьше :)
0
Тащемта это моя была реплика про 300МБ и youROCK не имеет никакого отношения к нему. Вот моя статистика:
$ find. \( -name "*.php" -o -name "*.js" -o -name "*.css" \) -exec cat {} \; | wc -l
7400511
$ find. \( -name "*.php" -o -name "*.js" -o -name "*.css" \) -exec cat {} \; | wc -c
283243229
Поводов для гордости не так уж и много — куча легаси, написанного не за один год. Уууу.
$ find. \( -name "*.php" -o -name "*.js" -o -name "*.css" \) -exec cat {} \; | wc -l
7400511
$ find. \( -name "*.php" -o -name "*.js" -o -name "*.css" \) -exec cat {} \; | wc -c
283243229
Поводов для гордости не так уж и много — куча легаси, написанного не за один год. Уууу.
+1
Серьёзные размерчики. Я стараюсь держать проекты в рамках 40K строк (без учёта фреймворка). Если проект становится больше — рефакторю, улучшаю архитектуру и в итоге минус несколько тыс. Строк кода. Так уже года три — функционал растёт, а размер не меняется!
+5
наверняка есть много дублирующего кода
0
есть. Не сильно дублирущего, не так-то и много тупого копи-паста, но он есть. Работаем над этим :)
0
Простая арифметика:
Если простой вывод из Бд занимает пять строк (строим массив) и он повторяется 300 раз, то уже экономим 1450 строк (1500 — 50 на формирование класса)
Если простой вывод из Бд занимает пять строк (строим массив) и он повторяется 300 раз, то уже экономим 1450 строк (1500 — 50 на формирование класса)
0
что-то уж очень много.
0
Вот и меня заинтересовало, что за проект с кодом в таком объеме.
Искусственный интеллект с памятью на MySQL?
Искусственный интеллект с памятью на MySQL?
+2
Вот вам смешно, а я ведь действительно отчасти похожими вещами и занимаюсь :(. До искусственного интеллекта, конечно, не дотягивает, но логика порой бывает оооочень сложная, и да, как ни странно, память именно на MySQL, ибо больше никто так компактно хранить информацию не умеет (кроме других реляционных СУБД, конечно же)
-1
а что здесь странного?
0
Поправил статью, написав чуть более ясно, что под этим подразумевается
0
Огромное спасибо!
SHOW SESSION STATUS LIKE 'handler_%' -- магия ;)!
+3
Ставим Percona Server, включаем handler socket и радуемся жизни :)
p.s. Percona Server — это форк MySQL, со всякими оптимизациями.
p.s. Percona Server — это форк MySQL, со всякими оптимизациями.
0
От запросов, которые требуют FULL SCAN на 100 000 строк (потому что индексов соответствующих нет) даже Percona не спасет, я думаю ;)
+1
Хм… а как потестить производительность, если нет такой объёмной БД?
0
Если такой объемной БД нет, то и проблем у вас, скорее всего, тоже не будет с этим :). Ну попробуйте сделать JOIN для всех таблиц, что у вас есть по условию 1=1 — я думаю, на 100 000 строк сможете набрать даже с 3 таблицами
+1
Нагуглил пакет sysbench и с его помощью потестировал :)
pastebin.com/eHXRbaTb
Правда сравнить не с чем. Тестировалось на виртуалке с ubuntu server 11.10. 70% от 2 ядер E8400@3.33Ghz, 512mb ram.
pastebin.com/eHXRbaTb
Правда сравнить не с чем. Тестировалось на виртуалке с ubuntu server 11.10. 70% от 2 ядер E8400@3.33Ghz, 512mb ram.
0
Сделать тестовое наполнение БД. Не зря при разработке высоконагруженных систем выделяют даже команды подготовителей данных.
0
про EXPLAIN интересно…
0
Рискну посоветовать еще один полезный инструмент для профилирования работы бд: SHOW PROFILES
Более детально тут:
dev.mysql.com/doc/refman/5.0/en/show-profiles.html
Более детально тут:
dev.mysql.com/doc/refman/5.0/en/show-profiles.html
0
По-моему автор изобрёл внутреннюю стату Percona
+1
Про оптимизацию запросок как-то мало, я бы еще добавил денормализацию, избавление от групбаев, джойнов. Да и о кешировании как-то глухо.
+2
Да, про собственно оптимизацию запросов я специально ничего не писал, потому что статей на эту тему не просто много, а очень много, и здесь, как раз, серебряной пули нет, к сожалению
+1
А джойны чем плохи? Иногда без них никак.
0
> EXPLAIN в MySQL зачастую нагло врёт.
С чего это он врёт? Конечно, никто 100% точности от него не ожидает, но тут он, скорее всего, говорит правду.
С чего это он врёт? Конечно, никто 100% точности от него не ожидает, но тут он, скорее всего, говорит правду.
+1
С помощью этой методики мне удалось выявить узкие места и снизить времена исполнения большинства страниц на сайте на Symfony с ~1000 ms до где-то 200-300 ms и добавить в дев-версию инструмент для автоматического предупреждения подобных проблем в будущем.Это еще раз доказывает, что если хочешь написать Высокопроизводительный порект, или с проект с притензией на Hiloa, то забей на всякие там Симфони и Друпалы и тому подобное…
Решил как-то наш IT начальник использовать ОперКарт. В результате пришлось переписать весь фронтэнд (в том числе и из-за нового интерфейса). По кучи запросов на страницу — это жесь. По одному селекту на вывод одной ветки дерева — это вообще песня…
В результатеот ОпенКарта осталась одна админка, которая использовалась и то на 10%, так как пришлось добавлять кучу своего функционала.
0
200-300 ms — тоже жесть, у меня в проекте по 20-40 ms на полное формирование стр.
0
Полностью согласен, что для хайлоада симфони или drupal — не лучший выбор. Но, к сожалению, этот выбор был сделан до меня, а для себя лишь поставил задачу заставить это чудо хотя бы как-то шевелиться. С 200-300 ms на страницу уже можно жить, в принципе
+1
10 000 000 хитов в сутки это уже хайлоад или нет?
Я про sportbox.ru на Drupal, если что
Я про sportbox.ru на Drupal, если что
0
А сколько серверов, и каких, если не секрет, обеспечивают работу сайта?
0
6 фронтэндов для веба, не забываем про трансляции, когда до 45000 онлайн
1 сервер для спортивной статистики, пропущенные/забитые голы и всё такое.
1 сервер БД
3 мемкеша
+ девелоперское.
Но могу ошибаться, некоторые машины являются виртуальными машинами.
1 сервер для спортивной статистики, пропущенные/забитые голы и всё такое.
1 сервер БД
3 мемкеша
+ девелоперское.
Но могу ошибаться, некоторые машины являются виртуальными машинами.
+1
Долго искал в статье хоть какой-то намек на использование
Как же это вы забыли про штатный способ поиска узких мест?
log-slow-queries
и log-queries-not-using-indexes
. Не нашел.Как же это вы забыли про штатный способ поиска узких мест?
+1
Не то, чтобы я про него забыл, я его просто пропустил, как и много чего другого. slow log — это хорошо, но его нужно смотреть отдельно, и польза от него далеко не однозначная, ибо в slow log часто попадают вполне «легальные» запросы. По сути, предложенный мной метод почти полностью повторяет информацию, доступную в slow log, только без, собственно, использования slow log
0
То есть MySQL предоставляет вам надежный способ учесть:
а) чистое время исполнения запроса, без учета кэширования и времени построения плана и
бэ) количество реально просканированных записей
и даже построить по ним отчет (mysqldumpslow), но вы его пропускаете, потому что в него надо «смотреть отдельно»?
а) чистое время исполнения запроса, без учета кэширования и времени построения плана и
бэ) количество реально просканированных записей
и даже построить по ним отчет (mysqldumpslow), но вы его пропускаете, потому что в него надо «смотреть отдельно»?
0
Ладно, давайте поставим вопрос по-другому. Была задача — снизить времена исполнения страниц на сайте. Что дает нам slow log, в самом лучшем случае? Он дает нам непосредственно SQL-запросы, которые были исполнены. По этим SQL-запросам ещё нужно найти кусок кода, в котором происходит вызов этого запроса (что далеко не всегда очевидно, если используется ORM, а у нас она используется очень конкретно) и только потом его исследовать.
Итого, действия при работе со slow log'ом:
1) нужно туда не забывать смотреть (причём для того, чтобы был доступ к slow log'у, по сути, нужен доступ к контейнеру с СУБД)
2) нужно (вручную?) отсеять запросы, которые не исполняются на страницах, а исполняются где-либо ещё (например, в кроне)
3) отсеять «тормозные» запросы, вызванные случайными всплесками активности / длительными блокировками при дампе таблиц и тд
4) по найденному запросу догадаться, на какой части сайта он используется и найти соответствующий кусок кода
5) начать действовать
Конечно, slow log хорош, но он реально полезен только тогда, когда есть откровенно «тормозящие» запросы. Даже ситуацию с тем, что запросов очень много (и они относительно простые), и поэтому не попадают в slow log этот подход уже не решает (при этом, скажем, этот запрос прекрасно виден в SHOW FULL PROCESSLIST через раз).
В моей статье я пытался описать действия, которые можно ещё попробовать, когда стандартные и известные средства плохо помогают (счетчик числа/времен запросов на странице, slow log, авто-explain, авто-show profile, анализ с помощью SHOW FULL PROCESSLIST и наблюдения, «за что глаз зацепится», ...). Понятно же, что есть стандартные средства для диагностики запросов, просто их часто бывает недостаточно, и приходится выдумывать такие фокусы, которые предоставляют, по сути «живой» slow log прямо на странице.
Для более-сложных запросов, из моего опыта, временами блокировок/кеширования/построения плана запроса/оптимизации запроса можно пренебречь, хотя их в любом случае нужно тоже считать вместе с временем исполнения запроса, чтобы получить полную картину. В общем, slow log — это хорошо, но не всегда это позволяет решить конкретную задачу — ускорить исполнение страницы на сервере, а не просто найти все «медленные» запросы.
Итого, действия при работе со slow log'ом:
1) нужно туда не забывать смотреть (причём для того, чтобы был доступ к slow log'у, по сути, нужен доступ к контейнеру с СУБД)
2) нужно (вручную?) отсеять запросы, которые не исполняются на страницах, а исполняются где-либо ещё (например, в кроне)
3) отсеять «тормозные» запросы, вызванные случайными всплесками активности / длительными блокировками при дампе таблиц и тд
4) по найденному запросу догадаться, на какой части сайта он используется и найти соответствующий кусок кода
5) начать действовать
Конечно, slow log хорош, но он реально полезен только тогда, когда есть откровенно «тормозящие» запросы. Даже ситуацию с тем, что запросов очень много (и они относительно простые), и поэтому не попадают в slow log этот подход уже не решает (при этом, скажем, этот запрос прекрасно виден в SHOW FULL PROCESSLIST через раз).
В моей статье я пытался описать действия, которые можно ещё попробовать, когда стандартные и известные средства плохо помогают (счетчик числа/времен запросов на странице, slow log, авто-explain, авто-show profile, анализ с помощью SHOW FULL PROCESSLIST и наблюдения, «за что глаз зацепится», ...). Понятно же, что есть стандартные средства для диагностики запросов, просто их часто бывает недостаточно, и приходится выдумывать такие фокусы, которые предоставляют, по сути «живой» slow log прямо на странице.
Для более-сложных запросов, из моего опыта, временами блокировок/кеширования/построения плана запроса/оптимизации запроса можно пренебречь, хотя их в любом случае нужно тоже считать вместе с временем исполнения запроса, чтобы получить полную картину. В общем, slow log — это хорошо, но не всегда это позволяет решить конкретную задачу — ускорить исполнение страницы на сервере, а не просто найти все «медленные» запросы.
0
Аргументация понятна. Но, согласитесь, место ей в начале статьи, а не в подвале коментов.
0
Соглашаюсь, из моей статьи это могло быть не совсем ясно, что все «стандартные» способы тоже существуют, и что нужно пробовать именно их в первую очередь, а потом уже, если не получилось (а вероятность этого весьма ненулевая), читать мою статью :). Я просто сделал предположение, что люди, которые будут на хабре читать эту статью, уже всё, что знали, перепробовали, и надеятся здесь увидеть что-нибудь ещё, чего они не знали до этого. И, судя по количеству добавлений в избранное, я действительно смог рассказать что-то новое для большого количества людей, которые используют MySQL :)
0
Для поиска кода, из которого пришел запрос, есть очень простой прием: где–нибудь на нижнем уровне вашего ОРМ добавляете код, который будет автоматически комментировать запросы. В комментарии можно добавить все что угодно: название метода, глобальный счетчик запросов, кусок стектрейса.
Конечно, это не очень хорошо повлияет на QC (одинаковые данные могут кешироваться для разных запросов), но и никто не говорит, что это надо делать постоянно. Можно периодически включать в дебаг режиме для одного из слейвов.
Конечно, это не очень хорошо повлияет на QC (одинаковые данные могут кешироваться для разных запросов), но и никто не говорит, что это надо делать постоянно. Можно периодически включать в дебаг режиме для одного из слейвов.
0
EXPLAIN вроде как ни разу мне не врал. Единственное это то, что по какой-то причине индексы странно себя ведут порой. То есть, например, делаешь EXPLAIN и он показывает что-то похожее на ваши результаты, потом делаешь OPTIMIZE TABLE и он начинает показывать ожидаемо вменяемый результат. Ну и до того как делаешь OPTIMIZE, Cardinality у индексов выдаёт неверное значение. Отчего не знаю, как избавиться тем более, поэтому просто периодически делаю OPTIMIZE.
0
Есть несколько простых советов, которые подходят для большинства проектов: как достичь высокой производительности. Скорее всего, чтоб их раскрыть — это тема отдельной статьи.
Первое, надо по возможности исключить все JOIN, используем денормализацию.
Во вторых, кешируем все справочники и неизменные таблицы, не надеемся на Кеш Запросов. Эти данные вытеснятся другими пользовательскими данными. Склейку данных делаем на клиенте.
Третье — предварительная подготовка данных. Используем очереди и бэкграундовские процессы.
Четвертое — большие порции данных бьем на маленькие части (иногда это называют шардинг).
Пятое — для доступа к данным на чтение используем HandlerSocket, так же можно использовать на обновление данных, на вставку не советую. Не забываем, что Autoincrement в HS работает не так как бы нам хотелось.
Используя эти пять простых принципов, у меня ни когда БД не была узким местом.
Первое, надо по возможности исключить все JOIN, используем денормализацию.
Во вторых, кешируем все справочники и неизменные таблицы, не надеемся на Кеш Запросов. Эти данные вытеснятся другими пользовательскими данными. Склейку данных делаем на клиенте.
Третье — предварительная подготовка данных. Используем очереди и бэкграундовские процессы.
Четвертое — большие порции данных бьем на маленькие части (иногда это называют шардинг).
Пятое — для доступа к данным на чтение используем HandlerSocket, так же можно использовать на обновление данных, на вставку не советую. Не забываем, что Autoincrement в HS работает не так как бы нам хотелось.
Используя эти пять простых принципов, у меня ни когда БД не была узким местом.
+2
+3
Все это, конечно, хорошо, но магия работает только в том случае если на сервере вообще больше ничего не исполняется. Т.е. на продакшне да с более-менее интенсивной загрузкой этот метод зачастую будет показывать сколько лет бабушке Пушкина вместо реальных данных. Хотя метод, конечно же, интересный.
0
Метод был хорош — но уже морально устарел (для иннодб таблиц удобнее смотреть значение innodb переменных). Если граммотно настроить performance_schema то можно снимать статистику по запросу в режиме рельного времени и, если понимать какие строчки кода что обозначают, можно докапаться не только до истины, что у вас слишком активно читается табличка 1...0 раз, но и понять почему её нет предположим в кэше, а так же что более важно обнаружить другие более узкие места, которые не показываются в сессионных переменных.
+1
Странно что вы обращаете внимание сразу на количество строк. По-моему, первостепенным является нахождение запросов у которых происходит using filesort, using temporary table и using fullscan (в порядке уменьшения приоритетов) по мнению неточного Explain-а и преобразование их в такой вид, чтобы было using index. Это, ИМХО, решает примерно 70% потери производительности. Дальше уже можно делать профайлинг, изучать количество строк, убирать из выборки лишние столбцы, кешировать, денормализовать структуру и т.д.
Тем не менее за ваш магический метод спасибо, не знал про него. Изучу обязательно.
P.S. Я обычно выдаю предупреждения на dev-сервере как раз если в Explain-е встречается filesort и temporary table. Когда одновременно, предупреждение жирное :)
Тем не менее за ваш магический метод спасибо, не знал про него. Изучу обязательно.
P.S. Я обычно выдаю предупреждения на dev-сервере как раз если в Explain-е встречается filesort и temporary table. Когда одновременно, предупреждение жирное :)
+1
Запросы
и
принципиально разные. И если у нас есть индекс по полю
SELECT * FROM some_table WHERE some_field = 100500 ORDER BY id LIMIT 100
и
SELECT * FROM some_table WHERE some_field <> 0 ORDER BY id LIMIT 100
принципиально разные. И если у нас есть индекс по полю
some_field
, то как раз в первом запросе не надо прочитывать 100500 строк, во втором — надо, так как условия там заданы разные. Или я чего-то крупно не понимаю?+1
Вы правы, в первом случае при наличии индекса запрос не займет значительного времени, даже при сотнях миллионов записей(ох, был у меня проект со статистикой...). Индексы — наше все!:)
-1
Товарищи, которые плюсуют этот комментарий, прочитайте описание структуры таблицы. Где вы там увидели индекс на some_field?
-1
Хм, действительно, в описании указан только индекс первичного ключа. В таком случае непонятно, почему «буду индекс праймаре использовать», так как он для поиска по
some_field
совершенно не нужен.0
Потому что стоит ORDER BY id
-1
В таком случае, лучше бы Вы реальный вывод EXPLAIN привели, а не свою интерпретацию. Потому что есть поле
possible_keys
, и есть key
, и они имеют разный смысл.0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Стратегия оптимизации веб-проекта с использованием MySQL