Комментарии 67
Еще полезно выбрать правильный сервер баз данных. В зависимости от задач оптимальным по быстродействию может быть и MySQL, и PostgreSQL, и Oracle, и mSQL…
>> list ($usec, $sec) = explode (' ', microtime());
Господа, ей богу, аргумент у microtime() уже ввели хз сколько лет назад. Хватит жить в прошлом веке.
>> WHERE FIND_IN_SET(12,otherproductids);
Вы шутите?! Такое писать в статье про оптимизацию.
>> Есть также и другой способ записать эти запросы, но без JOIN:
Если ключевого слова JOIN не видно — это не значит, что его там нет.
В общем и целом — статья противопоказана к чтению новичками, которые могут сделать из всей этой кучи слов неверные выводы.
>> Столбцы, которые используются в JOIN (в примере — customerid), должны быть проиндексированы в первую очередь.
Любые столбцы, используемые для поиска должны быть проиндексированы.
Господа, ей богу, аргумент у microtime() уже ввели хз сколько лет назад. Хватит жить в прошлом веке.
>> WHERE FIND_IN_SET(12,otherproductids);
Вы шутите?! Такое писать в статье про оптимизацию.
>> Есть также и другой способ записать эти запросы, но без JOIN:
Если ключевого слова JOIN не видно — это не значит, что его там нет.
В общем и целом — статья противопоказана к чтению новичками, которые могут сделать из всей этой кучи слов неверные выводы.
>> Столбцы, которые используются в JOIN (в примере — customerid), должны быть проиндексированы в первую очередь.
Любые столбцы, используемые для поиска должны быть проиндексированы.
Я согласен, некоторые приемы, описанные в статье, могут быть некорректными, но направление для поиска узких мест в производительности сайта эта статья даёт.
Библия может и врать про существование бога, но направление для праведной жизни она даёт…
Вместе с очень хорошими методиками (вроде замены NOW() на дискретное значение времени) — в статье настолько много воды и всяких «странных» утверждений типа:
>> Перед запуском этой функции следует подключиться к базе данных. Большинство современных сайтов делают это автоматически
>> Если на странице выводится сразу информация о 100 заказах, нужно будет делать уже 101 запрос.
(IN придумали для слабаков, ага)
>> Но таблица с заказами, вероятно, будет постоянно меняться — в этом случае нужно быть осторожнее с индексацией.
Постоянно?! Эта статья для новичков же — откуда у вас нагрузки амазона и ебея?!
>> wget -O /dev/null -q www.mywebsite.co.uk/runhourly.php
Ну и скриншот «сложного» (запрос с 2 джоинами с объединением по FK это теперь сложный!) запроса из WP, который мало того, что написан не совсем логично (условия из WHERE нужно перенести в ON, и да — я знаю, что оптимизатор mysql это и так сделает, но я говорю о семантике), так ещё и индексы нужные не проставлены (или mysql их не использует по непонятно каким причинам).
Повторюсь, в статье материал излагается сумбурно, как будто автор вспоминал по ходу дела все знания, которые накопил за всю практику. Мечется с одного, на другое, не раскрыв мысли и давая сомнительного качества аналогии.
Лично я на эту статью (перевод или оригинал, не принципиально) ссылаться как на «пособие» по оптимизации не стал бы — благо в документации по mysql есть обширная глава, которая покрывает всё описанное (и, естественно, гораздо глубже и в большем объёме).
>> Перед запуском этой функции следует подключиться к базе данных. Большинство современных сайтов делают это автоматически
>> Если на странице выводится сразу информация о 100 заказах, нужно будет делать уже 101 запрос.
(IN придумали для слабаков, ага)
>> Но таблица с заказами, вероятно, будет постоянно меняться — в этом случае нужно быть осторожнее с индексацией.
Постоянно?! Эта статья для новичков же — откуда у вас нагрузки амазона и ебея?!
>> wget -O /dev/null -q www.mywebsite.co.uk/runhourly.php
Ну и скриншот «сложного» (запрос с 2 джоинами с объединением по FK это теперь сложный!) запроса из WP, который мало того, что написан не совсем логично (условия из WHERE нужно перенести в ON, и да — я знаю, что оптимизатор mysql это и так сделает, но я говорю о семантике), так ещё и индексы нужные не проставлены (или mysql их не использует по непонятно каким причинам).
Повторюсь, в статье материал излагается сумбурно, как будто автор вспоминал по ходу дела все знания, которые накопил за всю практику. Мечется с одного, на другое, не раскрыв мысли и давая сомнительного качества аналогии.
Лично я на эту статью (перевод или оригинал, не принципиально) ссылаться как на «пособие» по оптимизации не стал бы — благо в документации по mysql есть обширная глава, которая покрывает всё описанное (и, естественно, гораздо глубже и в большем объёме).
Это перевод статьи. Если она вам не нравится, ставьте минус за статью, зачем карму минусовать? Выкладывают ведь такие статьи на SM, да и почти 50 добавивших в избранное за час ничего не значит?
Сударь, а я-то при чём?! Я вам поставил +1, за перевод. А в профиль минусовать карму вообще не ходил.
Обсуждаю я не качество перевода, а качество переводимого материала.
Обсуждаю я не качество перевода, а качество переводимого материала.
>> да и почти 50 добавивших в избранное за час ничего не значит
Лично для меня — нет, не значит. Я как считал статью бесполезной и вредной, так и считаю до сих пор.
Не принимайте мою критику на личный счёт — я обсуждаю материал (автором которого является другой человек), а не конкретно ваш перевод.
Лично для меня — нет, не значит. Я как считал статью бесполезной и вредной, так и считаю до сих пор.
Не принимайте мою критику на личный счёт — я обсуждаю материал (автором которого является другой человек), а не конкретно ваш перевод.
не мог удержаться, чтобы не сказать
«миллионы мух не могут ошибаться»
«миллионы мух не могут ошибаться»
> Любые столбцы, используемые для поиска должны быть проиндексированы.
Индексы бывают разными, в том же PostgreSQL есть возможность выбора между индексами на основе Хеша, B-дерева, R-дерева. Вопрос какой лучше?
B-дерево используется по умолчанию, но для поиска/выборок основанных на проверке равенства (WHERE… = ...) хеш-индекс должен быть быстрее, R-индекс в свою очередь должен быть быстрее при работе с геометрическими типами данных…
Я сказал «должен быть», потому что это теория, а на практике часто оказывается, что B-деревья быстрее (по крайней мере так было в старых версиях PostgreSQL. возможно в 9.* изменилось).
Что же касается выборок со сложными запросами, то есть еще Функциональные индексы (индекс не по значению данных, а по значению некоторой функции от них). Вот о них в первую очередь надо рассказывать новичкам, в разделе о построении индекса. Например, когда вы используете поиск по текстовым полям без учета регистра (а я обычно ищу без учета регистра), то можно построить такой индекс:
CREATE mytable_upper_text_key ON mytable (upper(mytext));
после этого наслаждаться ускорением запроса
SELECT id FROM mytable WHERE upper(mytext) = 'ИВАНОВ';
Индексы бывают разными, в том же PostgreSQL есть возможность выбора между индексами на основе Хеша, B-дерева, R-дерева. Вопрос какой лучше?
B-дерево используется по умолчанию, но для поиска/выборок основанных на проверке равенства (WHERE… = ...) хеш-индекс должен быть быстрее, R-индекс в свою очередь должен быть быстрее при работе с геометрическими типами данных…
Я сказал «должен быть», потому что это теория, а на практике часто оказывается, что B-деревья быстрее (по крайней мере так было в старых версиях PostgreSQL. возможно в 9.* изменилось).
Что же касается выборок со сложными запросами, то есть еще Функциональные индексы (индекс не по значению данных, а по значению некоторой функции от них). Вот о них в первую очередь надо рассказывать новичкам, в разделе о построении индекса. Например, когда вы используете поиск по текстовым полям без учета регистра (а я обычно ищу без учета регистра), то можно построить такой индекс:
CREATE mytable_upper_text_key ON mytable (upper(mytext));
после этого наслаждаться ускорением запроса
SELECT id FROM mytable WHERE upper(mytext) = 'ИВАНОВ';
Естественно. А в оракле ещё бывают битмапы. А ещё в оракле есть компрессия столбцов индексов. А ещё (в куче субд) есть function-based индексы (вы про них сказали, угу). Я не говорил, что индексы — простой инструмент. Это сложный инструмент, и как любой инструмент он должен применяться контекстно, в зависимости от решаемой проблемы.
Но я-то говорил о том, что фраза из статьи про джоин и индексы натянута, ибо индексировать нужно всё.
Но я-то говорил о том, что фраза из статьи про джоин и индексы натянута, ибо индексировать нужно всё.
Статья мутная, я согласен. Похожа на причесанные заметки начинающего вебмастера, у которого сложилась полная начальная картина работы сайтов на основе бд.
А еще… каждый индекс будет замедлять изменения значений и советовать создание индексов на все поисковые поля — это чересчур категорично. Особенно битмапы.
Про битмапы — отличный аргумент :-) Буквально недавно на блокировку при обновлении битмапов наступал.
Но всё равно — это мало касается целевой аудитории статьи — новичков. У них и объёмов и нагрузок нет.
Но всё равно — это мало касается целевой аудитории статьи — новичков. У них и объёмов и нагрузок нет.
А по поводу «на все поисковые поля» — ну вот давайте представим, что у нас есть таблица хотя бы на 100М записей.
Какие категории запросов есть смысл не покрывать индексами? Навскидку могу придумать рабочие запросы из ПО и редкие запросы на аналитику. Для обоих типов я бы покрыл индексами всё что нужно.
Приведёте пример типов, когда этого делать не стоит?
Какие категории запросов есть смысл не покрывать индексами? Навскидку могу придумать рабочие запросы из ПО и редкие запросы на аналитику. Для обоих типов я бы покрыл индексами всё что нужно.
Приведёте пример типов, когда этого делать не стоит?
Для кого эта статья?
«Сокращаем количество запросов, используя JOIN»
— Выпал в осадок. Благодаря таким как Вы, мы имеем тысячи быдлокодеров, которые не умеют правильно использовать JOIN. Ни слова о том, что не следует применять JOIN на большие таблицы.
К тому же phpMiniAdmin — медленный, небезопасный и ограниченный по функциональности. Я лично советую использовать HeidiSQL.
— Выпал в осадок. Благодаря таким как Вы, мы имеем тысячи быдлокодеров, которые не умеют правильно использовать JOIN. Ни слова о том, что не следует применять JOIN на большие таблицы.
К тому же phpMiniAdmin — медленный, небезопасный и ограниченный по функциональности. Я лично советую использовать HeidiSQL.
>> Ни слова о том, что не следует применять JOIN на большие таблицы.
Слишком безапелляционно :-) Что не так с джоином и большими таблицами?
Слишком безапелляционно :-) Что не так с джоином и большими таблицами?
Попробуйте JOIN-ом бездумно соединить пару таблиц, в которых по несколько миллионов записей — это может занять очень много времени, т.к. при этом создаётся ещё более огромная таблица.
JOIN — хороший и удобный инструмент, но он всё таки имеет некоторые ограничения в применении.
JOIN — хороший и удобный инструмент, но он всё таки имеет некоторые ограничения в применении.
ну в принципе любой бездумный запрос может занять очень много времени :)
это может занять очень много времени, т.к. при этом создаётся ещё более огромная таблица.
кто вам такую глупость сказал? О.о
попробуйте так же бездумно сделать select по этим же таблицам. выяснится, что join ничем не хуже select'ов.
Все просто. Если не накладывать на выборку никаких ограничений, то действительно результатом запроса будет здоровая временная таблица. Но, если гармотно наложить условия выборки, то нормальный оптимизатор запросов сначала отфильтрует входящие в запрос таблицы и лишь потом будет джойнить то что от них осталось, таким образом в результате джойна десятка многомиллионных таблиц можно получить вменяемое количество строк почти мгновенно. Просто нужно понимать как себя ведет оптимизатор и грамотно накладывать условия выборки. А для этого нужно либо знать, либо анализировать execution plan/explain/etc.
ППКС
ну в принципе любой бездумный запрос может занять очень много времени :)
ППКС
Всё так. Правда, работают медленно. Еще и лочат таблицы, создавая очередь запросов.
Для среднего магазина может быть и не критично, а вот для какой-дь онлайн-игры — очень даже.
Для среднего магазина может быть и не критично, а вот для какой-дь онлайн-игры — очень даже.
>HeidiSQL
А мне вот нравится EMS MySQL Manager, или DevArt dbforge for Mysql, на худой конец.
И про джойны на больших таблицах хотелось бы услышать. Если кв какой-нибудь реализации SQL они работают отвратно то это еще не значит что так везде. Опять же джойн джойну рознь, и без проверки планов выполнения говорить о том что «это зло» рановато, имхо.
А мне вот нравится EMS MySQL Manager, или DevArt dbforge for Mysql, на худой конец.
И про джойны на больших таблицах хотелось бы услышать. Если кв какой-нибудь реализации SQL они работают отвратно то это еще не значит что так везде. Опять же джойн джойну рознь, и без проверки планов выполнения говорить о том что «это зло» рановато, имхо.
Переименуйте в «как чуток соптимизировать сайт, сделанный быдлокодером».
Не относится к личной БД, но все же обратите внимание на скорость загрузки внешних дополнений (если они у вас есть): «оставьте отзыв», «одна кнопка» и т.п. которые встраиваются в html.
Мой «site performance» они просадили с 0,5сек до 2,7сек.
Мой «site performance» они просадили с 0,5сек до 2,7сек.
Аналогично. Яндексовые счётчик и реклама загружаются медленнее, чем сайт.
Тогда добавлю ещё «google-analytics.com» (300мс), накинул мне 50% времени.
Но он очень хорош.
Но он очень хорош.
А вы их после загрузки встраивайте. Без них пользователь как-нибудь перекантуется пару секунд.
Даешь инновационные идеи на хабре!
Автор, а теперь сравните вашу статью по полезностью, к примеру, с этой: webcrunch.ru/library/development/mysql/mysql-optimization/ (2 ссылка в Гугле по запросу «оптимизация mysql логи запросов»)
Наткнувшись в статье про оптимизацию БД на SELECT * FROM сразу бросил читать это…
Сейчас изучаю как устроен небольшой интернет магазин, 50% кода по объему это инсерты и селекты в таблицах с десятками полей, которые естественно перегоняются в обычные ассоциативные массивы.
Возникает вопрос а нафига козе боян, т.е. все эти SQL базы, навороты поверх в виде кеширования мемкешед? Не проще ли хранить массивы в нативном формате прямо в оперативной памяти? Только за счет неиспользуемых полей экономим разы в объемах.
В конце концов небольшая БД пусть со 100.000 объектов по килобайту это всего 100Мбайт оперативной памяти, т.е. SQL еще не нужен.
А БД с миллиардом записей и десятками тысяч подключений уже для SQL уже слишком тяжелый процесс, там уже отказ от единого сервера и переход к noSQL.
Не пора ли уже что то придумать, чем заниматься оптимизацией архаизмов?
Возникает вопрос а нафига козе боян, т.е. все эти SQL базы, навороты поверх в виде кеширования мемкешед? Не проще ли хранить массивы в нативном формате прямо в оперативной памяти? Только за счет неиспользуемых полей экономим разы в объемах.
В конце концов небольшая БД пусть со 100.000 объектов по килобайту это всего 100Мбайт оперативной памяти, т.е. SQL еще не нужен.
А БД с миллиардом записей и десятками тысяч подключений уже для SQL уже слишком тяжелый процесс, там уже отказ от единого сервера и переход к noSQL.
Не пора ли уже что то придумать, чем заниматься оптимизацией архаизмов?
«Не проще ли хранить массивы в нативном формате прямо в оперативной памяти?»
Есть такое — Oracle TimesTen, но там свои проблемы.
Есть такое — Oracle TimesTen, но там свои проблемы.
В нормальных проектах надежность важнее скорости.
На этом все.
На этом все.
Простите, нормальные проекты используют MySQL?
Хороший SQL код это прежде всего хранимые процедуры — Oracle, Postgres. Почти все хорошие биллинги построены на хранимых процедурах и молотят терабайты данных в реалтайме. Вот там надежность.
И кстати, такая штука про которую я говорил есть и активно развивается, называется Redis. C надежностью там все хорошо, можно настроить запись на диск тремя способами.
Хороший SQL код это прежде всего хранимые процедуры — Oracle, Postgres. Почти все хорошие биллинги построены на хранимых процедурах и молотят терабайты данных в реалтайме. Вот там надежность.
И кстати, такая штука про которую я говорил есть и активно развивается, называется Redis. C надежностью там все хорошо, можно настроить запись на диск тремя способами.
Спасибо тем, кто видя отличное от своего мнение не утруждает себя написанием обоснованных комментариев, а молча бежит минусовать карму.
Благодаря вам я стараюсь прикладывать больше сил чтобы писать более интересные посты для хабра (чтобы иметь возможность иногда свободно писать что думаю). Надеюсь что голос потраченный на меня спасет другого парня, который разозлит вас еще больше.
Однако если повернутся лицом к реальности, когда разрабатывали SQL, то 1 Габайт был недостижимым размером для винчестеров. Сегодня невозможно купить планку оперативной памяти меньше 1Гб, а noSQL стремительно развиваются в сторону повышения надежности и удобства (с производительностью и масштабируемостью там изначально хорошо).
Благодаря вам я стараюсь прикладывать больше сил чтобы писать более интересные посты для хабра (чтобы иметь возможность иногда свободно писать что думаю). Надеюсь что голос потраченный на меня спасет другого парня, который разозлит вас еще больше.
Однако если повернутся лицом к реальности, когда разрабатывали SQL, то 1 Габайт был недостижимым размером для винчестеров. Сегодня невозможно купить планку оперативной памяти меньше 1Гб, а noSQL стремительно развиваются в сторону повышения надежности и удобства (с производительностью и масштабируемостью там изначально хорошо).
Автор не указал элементарные вещи. Например, то, что запрос
SELECT * FROM orders
выполняется медленнее, чем
SELECT столбец1, столбец2, все остальные столбцы FROM orders
SELECT * FROM orders
выполняется медленнее, чем
SELECT столбец1, столбец2, все остальные столбцы FROM orders
Более того — его результат не предсказуем для приложения при изменении структуры таблицы.
В двух конкретно приведённых запросах — не могли бы вы привести конкретный пример, когда эта «непредсказуемость» может привести к чему-то плохому?
Для определённости представим, что код был написан не последним идиотом и в коде мы обращаемся к столбцам по имени, а не по порядковому номеру.
Приведёте?
Для определённости представим, что код был написан не последним идиотом и в коде мы обращаемся к столбцам по имени, а не по порядковому номеру.
Приведёте?
Вот тут обсуждение: www.sql.ru/forum/actualthread.aspx?tid=831458&pg=-1
Я же попросил конкретный пример для конкретных двух запросов, когда результат будет «непредсказуем».
Изменение плана — достаточно непредсказуемо? Или исчезновение строк при использовании VPD и появлении в таблицы колонки, где прав не хватает? И еще куча примеров, которые там обозначены.
Изменение плана — это не изменение результата. Результат выполнения запроса — выборка. План — процесс его выполнения.
Про VPD — такого в оракле (?) не знаю, а мы говорим о mysql вообще.
Про VPD — такого в оракле (?) не знаю, а мы говорим о mysql вообще.
То есть если запрос стал работать неожиданно медленно, то это нормально?
Появление лишних столбцов в запросе тоже?
VPD — citforum.ru/database/oracle/vpd/
Появление лишних столбцов в запросе тоже?
мы говорим о mysql вообщеТо есть в mysql надо писать как попало? Странно…
VPD — citforum.ru/database/oracle/vpd/
Про VPD — очень клёво, спасибо! (недавно такую задачу решал костылём через вьюху + контекст).
Про остальное:
лично я привык писать код, который работает корректно при наличии необходимого набора столбцов, вне зависимости от наличия новых (которые я не использую так и так). Так что — нет, для меня появление лишних столбцов в коде не неожиданно, потому как поведение кода не изменится.
Про «неожиданно медленно» — вот из-за таких фраз новички потом на каждом углу и орут, что * это плохо (всегда). Опять же — перечисление столбцов не гарантирует быстрых выборок. Более того — перечисление столбцов быстрее только в ряде случаев (когда все они уже есть в индексе, например). Это частные случаи. Они должны оптимизироваться адресно, опытным ДБАшником (потому что часто программисты в деталях работы CBO не разбираются).
С другой стороны — бывают «широкие» таблицы по 20 столбцов, из которых нужно выбрать 10. В этом случае перечисление столбцов только ухудшит читабельность, не привнеся (почти наверняка) ничего к производительности (да, данных больше передаётся по сети, но их не всегда же настолько больше, что мы это заметим).
Дополнительно хочу отметить: я не защищаю * и не говорю, что select * нужно писать всегда, но я придерживаюсь мнения, что до тех пор, пока нет явной и очевидной причины перечислять столбцы — лично я оставлю *, для того чтобы запрос оставался более читабельным, как результат — более простым в поддержке.
Про остальное:
лично я привык писать код, который работает корректно при наличии необходимого набора столбцов, вне зависимости от наличия новых (которые я не использую так и так). Так что — нет, для меня появление лишних столбцов в коде не неожиданно, потому как поведение кода не изменится.
Про «неожиданно медленно» — вот из-за таких фраз новички потом на каждом углу и орут, что * это плохо (всегда). Опять же — перечисление столбцов не гарантирует быстрых выборок. Более того — перечисление столбцов быстрее только в ряде случаев (когда все они уже есть в индексе, например). Это частные случаи. Они должны оптимизироваться адресно, опытным ДБАшником (потому что часто программисты в деталях работы CBO не разбираются).
С другой стороны — бывают «широкие» таблицы по 20 столбцов, из которых нужно выбрать 10. В этом случае перечисление столбцов только ухудшит читабельность, не привнеся (почти наверняка) ничего к производительности (да, данных больше передаётся по сети, но их не всегда же настолько больше, что мы это заметим).
Дополнительно хочу отметить: я не защищаю * и не говорю, что select * нужно писать всегда, но я придерживаюсь мнения, что до тех пор, пока нет явной и очевидной причины перечислять столбцы — лично я оставлю *, для того чтобы запрос оставался более читабельным, как результат — более простым в поддержке.
Так что — нет, для меня появление лишних столбцов в коде не неожиданно, потому как поведение кода не изменится.
Про клопов по ссылке не прочитали значит? Допустим, в коде вам нужно 5 полей, а в таблице их 10-20-30, да еще и row-chaining… Поведение кода-то не изменится, но замедление будет фантастическим, кэш забьется ненужным мусором, да еще и таскать между базой и клиентом лишние мега/гигабайты ненужных данных…
В этом случае перечисление столбцов только ухудшит читабельностьнапротив, улучшит ясность — что и откуда берем. особенно в серьезных больших запросах.
Хорошая статья. Еще в 2000ом году такое читал.
А почему вы используете PHP-модуль mysql а не более современный и быстрый mysqli?
Не то чтобы плохая статья, но процент шизы (типа оптимизации таблиц после коннекта к базе) слишком высок, чтобы рекомендовать её новичку.
Такое ощущение, что автор неделю назад узнал, что бывает такая база данных — mysql, и именно она стоит на его блоге.
Не ту статью вы выбрали для перевода.
Такое ощущение, что автор неделю назад узнал, что бывает такая база данных — mysql, и именно она стоит на его блоге.
Не ту статью вы выбрали для перевода.
Это тот случай, когда комментарии несут больше полезной информации, чем сама статья.
так вот чего меня директор чуть не скушал, когда сайт начал загружаться за 3-4 секунды…
А почему про SphinxSearch никто ничего не сказал? Memcached упомянули, а сфинкс забыли.
Думаю не один я буду признателен, если автор перезальёт картинки. спасибо=)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Ускоряем базу данных веб-сайта