предисловие
- Я полагаю, что все слышали об индексе, но сколько людей на самом деле им пользуются? Когда я пишу SQL на работе, я действительно думаю о том, как этот SQL может использовать индекс и как повысить эффективность выполнения?
- В этой статье подробно описываются несколько принципов оптимизации индексов.Поскольку их можно применять в любое время на работе, я считаю, что SQL, который вы пишете, должен быть наиболее эффективным и мощным.
- Карта мозга статьи выглядит следующим образом:
Правила оптимизации индекса
1. Ведущий нечеткий запрос аналогичного утверждения не может использовать индекс
select * from doc where title like '%XX'; --不能使用索引
select * from doc where title like 'XX%'; --非前导模糊查询,可以使用索引
- Поскольку поиск по страницам строго запрещен, левый нечеткий или полный нечеткий, при необходимости вы можете использовать поисковую систему для решения.
2. Союз, в, или может все попасть в индекс, рекомендуется использовать в
-
union
Индексы могут быть поражены, а MySQL потребляет меньше всего ресурсов процессора.
select * from doc where status=1
union all
select * from doc where status=2;
-
in
Способен поразить индекс, соотношение ЦП оптимизации запросовunion all
Много, но на это можно не обращать внимания, рекомендуется использовать вообщеin
.
select * from doc where status in (1, 2);
-
or
Новая версия MySQL может попасть в индекс, а оптимизация запросов потребляет больше ресурсов ЦП, чемin
Слишком много, не рекомендуется для частого использованияor
.
select * from doc where status = 1 or status = 2
-
Пополнить: Некоторые места говорят в
where
используется в условияхor
, произойдет сбой индекса, что приведет к полному сканированию таблицы, что является недоразумением:
-
①Требования
where
Все поля, используемые предложением, должны быть проиндексированы; -
②Если объем данных слишком мал, mysql считает, что полное сканирование таблицы выполняется быстрее, чем поиск по индексу при формулировании плана выполнения, поэтому индекс не будет использоваться;
-
③Убедитесь, что версия mysql
5.0
Или больше, и оптимизатор запросов включенindex_merge_union=on
, то есть переменнаяoptimizer_switch
существуют вindex_merge_union
и дляon
.
3. Отрицательный условный запрос не может использовать индекс
-
Отрицательные условия:
!=
,<>
,not in
,not exists
,not like
Ждать. -
Например, следующая инструкция SQL:
select * from doc where status != 1 and status != 2;
- Может быть оптимизирован для запроса:
select * from doc where status in (0,3,4);
4. Крайний левый префиксный принцип совместного индекса
-
если в
(a,b,c)
Создайте совместный индекс по трем полям, тогда он автоматически создастa
|(a,b)
|(a,b,c)
индекс группы. -
Чтобы войти в бизнес-требования, оператор SQL выглядит следующим образом:
select uid, login_time from user where login_name=? andpasswd=?
- может построить
(login_name, passwd)
совместный индекс. Потому что бизнеса почти нет.passwd
требования одного условного запроса, в то время как существует множествоlogin_name
Требования к единым условным запросам, чтобы вы могли создавать(login_name, passwd)
совместный индекс вместо(passwd, login_name
).
- При создании сводного индекса поле с наибольшей степенью дискриминации находится в крайнем левом углу.
- Когда существует смешанное условие оценки незнака равенства и знака равенства, при создании индекса столбец условия знака равенства добавляется перед. как
where a>? and b=?
, то даже еслиa
является более дискриминационным и должен такжеb
Ставим на передний план индекс.
- При запросе крайнего левого префикса это не означает, что порядок оператора SQL должен соответствовать индексу соединения..
- Следующая инструкция SQL также может попасть
(login_name, passwd)
Этот совместный индекс:
select uid, login_time from user where passwd=? andlogin_name=?
- Но все же рекомендую
where
Последний порядок согласуется с общим индексом, и это хорошая привычка.
- если
index(a,b,c)
,where a=3 and b like 'abc%' and c=4
,a
может быть использован,b
может быть использован,c
____ не работает.
5. Столбец справа от условия диапазона в индексе использовать нельзя (индекс можно использовать для столбца диапазона), а индекс столбца после столбца диапазона недействителен.
- Условия полигона таковы:
<、<=、>、>=、between
Ждать. - До диапазона столбцов для индекса, если запрос имеет два полных диапазона столбцов, вы не можете использовать индекс.
- Если есть общий индекс
(empno、title、fromdate)
, то в следующем SQLemp_no
можно использовать индекс иtitle
иfrom_date
Индексы не используются.
select * from employees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'
6. Не делайте никаких операций (расчетов, функций) над колонками индекса, иначе индекс выйдет из строя и перейдет к полному сканированию таблицы
- Например, следующий оператор SQL, даже если
date
На таблице создается индекс, а также выполняется полное сканирование таблицы:
select * from doc where YEAR(create_time) <= '2016';
- Его можно оптимизировать как вычисление значения следующим образом:
select * from doc where create_time <= '2016-01-01';
- Например, следующая инструкция SQL:
select * from order where date < = CURDATE();
- может быть оптимизирован для:
select * from order where date < = '2018-01-2412:00:00';
7. Принуждение выполнит полное сканирование таблицы
- Строковый тип без одинарных кавычек приведет к сбою индекса, потому что mysql сам выполнит преобразование типа, что эквивалентно работе со столбцом индекса.
- если
phone
полеvarchar
тип, следующий SQL не может попасть в index.
select * from user where phone=13800001234
- может быть оптимизирован для:
select * from user where phone='13800001234';
8. Столбцы с частыми обновлениями и низкой дискриминацией данных не должны индексироваться.
-
Обновления изменят B+-дерево, а индексация часто обновляемых полей сильно снизит производительность базы данных.
-
«Пол» — это атрибут, который мало чем отличается. Строить индекс бессмысленно. Он не может эффективно фильтровать данные, а его производительность аналогична полному сканированию таблицы.
-
Дискриминация, как правило, более 80% времени может быть проиндексирована, может быть использована дискриминация
count(distinct(列名))/count(*)
вычислять.
9. Используйте покрывающий индекс для выполнения операций запроса, избегайте возврата к таблице и сокращайте использование select *
- Покрывающий индекс: количество запрашиваемых столбцов и установленный индекс одинаковы, а поля одинаковы.
- Для запрашиваемого столбца данные можно получить из индекса, вместо перехода к строке через row-locator, то есть «опрашиваемый столбец должен быть покрыт построенным индексом», что может ускорить запрос.
- Например, для регистрации бизнес-требований оператор SQL выглядит следующим образом.
Select uid, login_time from user where login_name=? and passwd=?
- может построить
(login_name, passwd, login_time)
совместный индекс , так какlogin_time
был установлен в индексе, запрошенныйuid
иlogin_time
не уходиrow
извлекает данные по нему, тем самым ускоряя запросы.
10. Индекс не будет содержать столбцов со значениями NULL
- Пока столбец содержит значения NULL, он не будет включен в индекс, если в составном индексе есть один столбец, содержащий
NULL
значение, столбец недопустим для этого составного индекса. Поэтому мы стараемся использовать все возможноеnot null
Ограничения и значения по умолчанию.
11, является нулевым, не нулевым, не может использовать индекс
12. Если есть сцены сортировки и группировки, обратите внимание на упорядоченность индекса
-
order by
Последнее поле является частью составного индекса и размещается в конце составного индекса, чтобы избежать сортировки файлов и повлиять на производительность запроса.
- Например, для заявления
where a=? and b=? order by c
, вы можете построить совместный индекс(a,b,c)
.
- Если в индексе есть диапазон поиска, то индекс незамечен, например
WHERE a>10 ORDER BY b;
,показатель(a,b)
Невозможно отсортировать.
13. Используйте короткие индексы (префиксные индексы)
-
Столбцы индексируются, и длина префикса должна быть указана, если это возможно. Например, если есть
CHAR(255)
столбец, если этот столбец стоит первым10
или20
个字符内,可以做到既使得前缀索引的区分度接近全列索引,那么就不要对整个列进行索引。因为短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作,减少索引文件的维护开销。 можно использоватьcount(distinct leftIndex(列名, 索引长度))/count(*)
для вычисления дискриминативности индекса префикса. -
Но недостаток в том, что его нельзя использовать для
ORDER BY
иGROUP BY
операции и не может использоваться для покрытия индексов. -
Однако во многих случаях нет необходимости индексировать все поля, и длину индекса можно определить в соответствии с фактическим распознаванием текста.
14. Используйте отложенную ассоциацию или подзапросы для оптимизации сценариев многостраничного пейджинга.
- MySQL не пропускает
offset
хорошо, но возьмиoffset+N
строку, затем вернуться, чтобы отбросить предыдущую строку смещения, и вернуть N строк, затем, когда смещение особенно велико, эффективность очень низкая, либо контролировать общее количество возвращаемых страниц, либо выполнять перезапись SQL для количества страниц, превышающих определенный порог. - Пример выглядит следующим образом: сначала быстро найдите то, что нужно приобрести
id
сегмент, а затем связать:
selecta.* from 表1 a,(select id from 表1 where 条件 limit100000,20 ) b where a.id=b.id;
15. Если ясно, что возвращается только один результат, ограничение 1 может повысить эффективность
- Например, следующий оператор SQL:
select * from user where login_name=?;
- может быть оптимизирован для:
select * from user where login_name=? limit 1
- Я четко знаю, что есть только один результат, но база данных этого не знает, поэтому я говорю ей активно останавливать движение курсора.
16. Лучше не присоединяться более чем к трем столам
-
Типы данных полей, которые необходимо объединить, должны быть одинаковыми.При запросе нескольких таблиц убедитесь, что связанные поля должны иметь индексы.
-
Например:
left join
Он определяется левой стороной, а данные в левой части должны его иметь, поэтому правая сторона является нашей ключевой точкой,Чтобы построить индекс, вам нужно правильно построить. Конечно, если индекс слева, вы можете использоватьright join
.
17. Рекомендуется контролировать индекс одной таблицы в пределах 5
18. Типа в SQL оптимизация производительности объясните: как минимум уровень диапазона, требование это уровень ref, если он может быть константой, то лучше
-
consts
: в одной таблице имеется не более одной совпадающей строки (первичный ключ или уникальный индекс), и данные могут быть прочитаны на этапе оптимизации. -
ref
: использовать обычный индекс(Normal Index)
. -
range
: выполнить поиск диапазона по индексу. -
когда
type=index
Когда физический файл индекса полностью просканирован, скорость очень низкая.
19. Поля с уникальными характеристиками в бизнесе, даже если это комбинация нескольких полей, должны создавать уникальный индекс
- Не думайте, что это влияет на уникальные индексы
insert
Скорость, эта потеря скорости незначительна, но прирост скорости поиска очевиден. Кроме того, даже если на прикладном уровне выполняется очень полный контроль проверки, пока нет уникального индекса, согласно закону Мерфи должны генерироваться грязные данные.
20. Избегайте следующих заблуждений при создании индексов
-
Чем больше индексов, тем лучше. Если вы считаете, что вам нужен запрос, создайте индекс.
-
NingqueWulan, что индекс потребляет пространство, серьезная замедляющая скорость обновлений и дополнений.
-
Сопротивляйтесь уникальному индексу и думайте, что уникальность бизнеса нужно решать методом «сначала проверить, а затем вставить» на прикладном уровне.
-
Оптимизация преждевременно, оптимизация без знания системы.
Избирательность индексов и индексация префиксов
-
Поскольку индекс может ускорить выполнение запроса, необходимо ли создавать индекс до тех пор, пока он требуется оператору запроса? ответ отрицательный. Несмотря на то, что индекс увеличивает скорость выполнения запросов, он также имеет свою цену: сам файл индекса занимает место в хранилище, а индекс увеличивает нагрузку на вставку, удаление и изменение записей. Кроме того, MySQL также потребляет ресурсы для обслуживания индекса. во время выполнения, поэтому больше индексов не всегда лучше. Вообще не рекомендуется строить индекс в двух случаях.
-
Первый случай заключается в том, что записи таблицы относительно малы, например, таблица с одной или двумя тысячами или даже всего несколькими сотнями записей, нет необходимости создавать индекс, просто позвольте запросу выполнить полное сканирование таблицы. Насчет того, сколько записей считать лишним, у этого человека личное мнение.Мой личный опыт - использовать в качестве разделительной черты 2000. Если количество записей не превышает 2000, то можно считать, что индекс не строить, а если количество записей превышает 2000, индексация может считаться целесообразной.
-
В другом случае не рекомендуется строить индекс, если индекс селективности низкий. Так называемый индекс селективности (Selectivity), который представляет собой уникальное значение индекса (также называемое базовым, Cardinality) и записывает отношение номера таблицы (#T):
Index Selectivity = Cardinality / #T
- Очевидно, диапазон избирательности
(0, 1]``,选择性越高的索引价值越大,这是由
B+Tree的性质决定的。例如,
employees.titles表,如果
Поле title часто запрашивается отдельно, нужно ли его индексировать или нет, давайте посмотрим на его избирательность:
SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles;
+-------------+
| Selectivity |
+-------------+
| 0.0000 |
+-------------+
-
title
отсутствие избирательности0.0001
(Точное значение — 0,00001579), поэтому нет необходимости индексировать его отдельно. -
Существует стратегия оптимизации индекса, связанная с избирательностью индекса, называемая префиксным индексом, в которой в качестве ключа индекса используется префикс столбца, а не всего столбца. полный индекс столбца.. Более короткие ключи индекса уменьшают размер файла индекса и накладные расходы на обслуживание. Ниже с
employees.employees
Таблица в качестве примера для ознакомления с выбором и использованием индекса префикса. -
Предполагая, что таблица сотрудников имеет только один индекс
, тогда, если мы хотим найти человека по имени, мы можем выполнить только полное сканирование таблицы:
EXPLAIN SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido';
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 300024 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
- Если вы часто ищете сотрудников по имени, это явно неэффективно, поэтому мы можем рассмотреть возможность создания индекса. Есть два варианта, построить
<first_name>
или<first_name, last_name>
, посмотрите на селективность двух индексов:
SELECT count(DISTINCT(first_name))/count(*) AS Selectivity FROM employees.employees;
+-------------+
| Selectivity |
+-------------+
| 0.0042 |
+-------------+
SELECT count(DISTINCT(concat(first_name, last_name)))/count(*) AS Selectivity FROM employees.employees;
+-------------+
| Selectivity |
+-------------+
| 0.9313 |
+-------------+
-
<first_name>
Очевидно, что избирательность слишком низкая, ``选择性很好,但是
first_name和
last_name加起来长度为
30,有没有兼顾长度和选择性的办法?可以考虑用first_name和last_name的前几个字符建立索引,例如
`, чтобы увидеть его избирательность:
SELECT count(DISTINCT(concat(first_name, left(last_name, 3))))/count(*) AS Selectivity FROM employees.employees;
+-------------+
| Selectivity |
+-------------+
| 0.7879 |
+-------------+
- Селективность неплохая, но до 0,9313 все же далековато, поэтому добавим префикс last_name к 4:
SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM employees.employees;
+-------------+
| Selectivity |
+-------------+
| 0.9007 |
+-------------+
- В это время селективность уже идеальна, а длина этого индекса всего
18
,Сравнивать<first_name, last_name>
Почти в половине случаев мы строили этот префиксный индекс:
ALTER TABLE employees.employees
ADD INDEX `first_name_last_name4` (first_name, last_name(4));
- На этом этапе снова выполните запрос по имени и сравните и проанализируйте результаты перед индексированием:
SHOW PROFILES;
+----------+------------+---------------------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+---------------------------------------------------------------------------------+
| 87 | 0.11941700 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' |
| 90 | 0.00092400 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' |
+----------+------------+---------------------------------------------------------------------------------+
-
Прирост производительности значителен: запросы выполняются более чем в 120 раз быстрее.
-
Префиксный индекс учитывает размер индекса и скорость запроса, но его недостаток в том, что его нельзя использовать для
ORDER BY
иGROUP BY
операции и не может использоваться дляCovering index
(то есть, когда сам индекс содержит все данные, необходимые для запроса, доступ к самому файлу данных больше не осуществляется).
Суммировать
- В этой статье в основном рассказывается о 20 принципах оптимизации индексов, надеюсь, она понравится читателям.
- эта статья
脑图
иPDF文档
Он готов, и нуждающиеся партнеры могут подписаться на общедоступную учетную запись WeChat [Code Ape Technology Column], чтобы отвечать на ключевые слова.索引优化
Получать.