Много раз «проблема с производительностью», которая возникает в нашей программе, на самом деле является проблемой с «массовым» кодом, который мы написали, проблемой с нашим собственным кодом и проблемой с использованием операторов DML Mysql. Ниже приводится краткое изложение моментов, на которые следует обратить внимание при использовании операторов MySQL DML.
заselect *
Всегда будьте осторожны
В большинстве случаев не требуетсяselect *
из. После использования такого оператора оптимизация, такая как сканирование покрытия индекса, не может быть выполнена оптимизатором, и будут добавлены дополнительные операции ввода-вывода, памяти и потребления ЦП.
Конечно, используяselect *
Не все так плохо, используйте это с умомselect *
Это может упростить разработку и повысить возможность повторного использования одного и того же кода.
Было ли просканировано слишком много дополнительных записей
Иногда обнаруживается, что некоторым запросам может потребоваться прочитать тысячи строк данных, но вернуть лишь несколько или очень мало результатов. Для оптимизации можно использовать следующие методы:
- Посмотрите, можете ли вы изменить структуру таблицы. Например, с помощью сводной таблицы
- Посмотрите, является ли способ получения результатов данных лучшим, и является ли дорога уже самой короткой.
- Используя покрывающий индекс, поместите все необходимые столбцы в индекс, чтобы сократить шаги выборки данных из соответствующей строки в возвращаемой таблице.
Разделить некоторые операторы SQL
В традиционной интернет-системе подчеркивается, что сетевых соединений должно быть как можно меньше, а уровень данных должен выполнять как можно больше работы за одно соединение, чтобы предотвратить установление множественных соединений.Однако эта идея не применима к MySQL.MySQL спроектирован так, чтобы разрешать соединения, а Disconnects очень легкие и могут поддерживать более 100 000 запросов в секунду на типичном сервере.
Поэтому в некоторых сценариях большой запрос можно «разделять и властвовать», разбивать на маленькие запросы, а затем объединять. Например следующая ситуация:
- Для полного запроса данных он становится разбиением на страницы. Если в таблице десятки миллионов фрагментов данных, выбрать все за один раз определенно невозможно. Его можно заменить, принимая порцию за раз и разделяя давление на один раз.
- При удалении большого количества старых данных рекомендуется не очищать большую выписку за один раз.
一次删一万条
. Если для одновременного выполнения используется большой оператор, может потребоваться заблокировать большой объем данных за один раз, занимая большое количество транзакций журнала, и позволить Mysql остановиться на этом.Чтобы избежать этой ситуации, он лучше всего удалять около 10 000 штук данных за один раз, а затем делать паузу на некоторое время после каждого удаления, чтобы разогнать разовую нагрузку на сервер.
Примечание. Хотя Mysql устанавливает соединение очень легко, это не означает, что его можно запрашивать один за другим в цикле, а затем соединять, поэтому эффективность по-прежнему очень низкая, и обычно это точка оптимизации sql в работе.
Используйте с осторожностьюjoin
действовать
Это считается табу. Многие интернет-продукты компаний запрещают операцию объединения. Вместо этого сначала извлеките идентификатор данных из одной таблицы, а затем используйте его из другой таблицы.where in
Две операции запроса одной таблицы для запроса. В основном по следующим причинам:
- Сделайте кеш приложения (redis, memcache и т. д.) более эффективным. Например, если некоторые идентификаторы запрашиваются в первой таблице, если кеш попал, оператор where in можно опустить.
- Легче заниматься развитием бизнеса, удобно разбивать базу данных, проще добиться высокой производительности и высокой расширяемости.
- После сортировки идентификаторов в порядке возрастания эффективность запроса становится более эффективной, чем случайная ассоциация соединения.
- Сократите избыточные запросы. Двойной запрос на уровне приложения означает, что приложению нужно запросить запись только один раз, в то время как при использовании объединения может потребоваться повторное сканирование для доступа к части данных.
- Запрос к одной таблице может снизить количество конфликтов при блокировках.
Если его необходимо использовать, его можно оптимизировать следующими способами:
- удостовериться
ON
илиusing
В предложении есть индекс столбца - обеспечить, чтобы любой
group by
иorder by
Выражения в относятся только к одному столбцу в таблице.
В сценариях с высокими требованиями к производительности избегайте его использования в запросах.临时表
Временное представление MySQL не имеет индексов, использование временных таблиц обычно означает снижение производительности, поэтому в сценариях с высокими требованиями к производительности лучше не использовать операции с временными таблицами:
- на неиндексированных полях
group by
работать. -
UNION
Запрос. - Подзапросы в запросах.
- часть
order by
такие операции, какdistinct
функция иorder by
используется вместе иdistinct
иorder by
то же поле. Например, в некоторых случаяхgroup by
иorder by
Поля разные.
Использовать ли временную таблицу, вы можете передатьexplain
видеть, видетьExtra
результат столбца, если он присутствуетUsing temporary
вам нужно обратить внимание.
count()
оптимизация функций
count()
Функция требует особого внимания: она не считает поля со значением NULL! Следовательно: вы не можете указать столбец результата запроса для подсчета количества строк результата. которыйcount(xx column)
не слишком хорошо.
Если вы хотите подсчитать набор результатов, используйтеcount(*)
, производительность также будет хорошей.
Старайтесь не использовать подзапросы
Старайтесь не использовать подзапросы, вместо этого используйте ассоциации
Оптимизировать разбиение на страницыlimit
Обычно, когда мы разбиваем страницы, мы обычно используемlimit 50, 10
такое заявление. Меньше данных — это хорошо, но производительность может быть проблемой, когда смещение данных очень велико, например.select xx,xxx from test_table limit 100000020, 20
. После сканирования 100000020 фрагментов данных было возвращено только 20 фрагментов данных. В настоящее время мы можем использовать следующие два способа оптимизации:
использоватьbetween and
и индекс первичного ключа
Используя первичный ключ для увеличения идентификатора, если мы знаем верхнюю границу пейджинга, приведенный выше запрос можно переписать как:select xxx, xxx from test_table where id between xxxxx and xxxx
.
Используйте самоувеличивающийся индекс первичного ключа,order by
добавлятьlimit
, без использования смещения
limit
иoffset
Проблема, собственно, в том, чтоoffset
Проблема заключается в том, что MySQL сканирует большое количество ненужных строк, а затем отбрасывает их. Если вы используете определенную метку для записи позиции данных, снятых в прошлый раз, вы можете начать сканирование непосредственно с позиции закладки в следующий раз, чтобы избежать использованияoffset
.
Например, приведенный выше запрос можно изменить на:
Первый набор данных: «выбрать xxx, xxxx из таблицы test_table по id desc limit 20;
Таким образом, получается значение идентификатора декомпозиции текущих данных и следующих данных, и запрос следующей страницы может знать, что:select xxx, xxx from test_table where id < '上页id分界值' order by id desc limit 20
Знакомый и гибкийexplain
Ниже приведен весь процесс выполнения запроса mysql,explain
Вы можете видеть красную часть рисунка,
explain
Будет отображаться много полей и содержимого, и содержимое часто трудно запомнить.При использовании вы можете просмотреть следующие диаграммы:объяснить диаграмму