Ihar Hancharenka 807fe7547d m
2025-01-06 09:37:26 +03:00

458 строки
64 KiB
Plaintext
Исходник Ответственный История

Этот файл содержит невидимые символы Юникода

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

************************************************************************************
В первой части (https://t.me/pg_guru/713) мы с вами узнали причины, по которым у PostgreSQL может не получаться использовать индекс, в этой части мы рассмотрим причины по которым PostgreSQL может не хотеть использовать индекс.
1⃣ Неправильные настройки стоимости операций выполнения запросов.
О настройках оценки стоимости запросов планировщиком мы уже писали. (https://t.me/pg_guru/707) Если вы накосячили в этих настройках, то планировщик PostgreSQL может отдавать предпочтение последовательному сканированию вместо поиска по индексу, считая сканирование более производительным. Так что будьте осторожны с этими настройками.
Есть еще одна настройка, которая может повлиять на поведение планировщика, называется она enable_seqscan. Если мы ее поставим в значение off, то это не значит, что мы совсем отключим последовательное сканирование, просто планировщик будет предпочитать сканирование по индексу. Учтите, что не во всех случаях сканирование по индексу может быть более производительным чем последовательное сканирование. Так что с этой настройкой тоже будьте аккуратны.
2⃣ Маленькая таблица с данными.
Если у вас небольшая таблица (100 строк или меньше), то планировщик PostgreSQL может решить, что последовательное сканирование будет более быстрым, даже для запросов с высокой селективностью. И здесь может быть и не стоит заставлять планировщик использовать индекс, так как действительно последовательное сканирование будет быстрее.
В любом случае нужно смотреть план запроса и скорость его выполнения при использовании индекса и без него.
3⃣ Запрос возвращает большее количество строк таблицы.
Если у вас запрос с малой селективностью, т.е. возвращается бОльшая часть строк таблицы, то здесь тоже планировщик PostgreSQL может предпочесть последовательное сканирование. При каком кол-ве возвращаемых строк планировщик может предпочесть последовательное сканирование неизвестно. Опять же, EXPLAIN вам в помощь 😉
4⃣ Использование оператора LIMIT.
С помощью LIMIT мы ограничиваем кол-во выводимых строк в результате запроса, по этому тут как и случаях 2⃣ и 3⃣ планировщик может предпочесть последовательное сканирование, что может быть гораздо медленнее использования индекса на больших таблицах. По этому используйте LIMIT с осторожностью в запросах.
5⃣ Неактуальная статистика.
Планировщик при принятии решения о выполнении того или иного плана запроса в первую очередь опирается на статистику. Если статистика в базе неактуальная, то планировщик может посчитать кол-во строк меньшим, чем есть на самом деле в таблице и предпочесть последовательное сканирование вместо индекса. По этому актуальность статистики очень важна.
Но может случиться так, что у вас в базе случилась какая-то массовая загрузка данных и VACUUM еще не успел придти в такие таблицы с новыми данными и собрать новую статистику. Пока VACUUM этого не сделает, запросы к этим таблицам могут выполняться совсем неоптимальным образом.
Если у вас в базе массовая загрузка данных происходит очень часто, то имеет смысл вручную или по расписанию дополнительно обновлять статистику, не дожидаясь когда это сделает VACUUM.
Это все, на наш взгляд, основные причины, по которым планировщик PostgreSQL может не использовать индекс. Если знаете еще какие-то, то пишите в комментариях к посту 👇 😉
************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.************************************************************************************
Захотели мы ускорить запрос, создали индекс по нужной колонке таблицы и успокоились. А PostgreSQL не использует, созданный нами индекс и продолжает делать последовательное сканирование по таблице, например. В этой серии постов попытаемся разобраться почему так может происходить.
В расследовании проблем с индексами лучший наш друг, это команда EXPLAIN. Она, конечно, не покажет нам точную причину неиспользования индекса PostgreSQL, но по крайней мере задаст направление, в котором нам следует производить расследование.
При расследовании проблем с индексами можно использовать несколько приемов. Например, если PostgreSQL использует не тот индекс, на который вы надеялись, то вы можете явно открыть транзакцию, удалить в ней индекс, выполнить запрос, посмотреть его план, а потом транзакцию откатить. Или вы можете использовать расширение для создания гипотетических индексов HypoPG, о котором мы уже писали (https://t.me/pg_guru/344), чтобы смоделировать различные ситуации выполнения запроса и использования индекса.
PostgreSQL может не использовать индекс по двум глобальным причинам:
✅ Потому что не может использовать созданный индекс;
✅ Потому что считает, что использование индекса не приведет к увеличению производительности выполнения запроса.
У первой причины есть несколько вариантов:
1⃣ Индекс не существует ( забыли создать, например 😅);
2⃣ Функция препятствует использованию индекса.
Здесь уже ситуация посложнее чем в первом варианте. Предположим, что у нас есть какой-то такой запрос:
SELECT * FROM table WHERE LOWER(email) = 'example@yandex.ru';
В запросе мы ищем конкретный email адрес, приведя его к нижнему регистру с помощью функции LOWER (). В данном случае PostgreSQL не будет использовать индекс на колонке email, даже если может.
Выходом будет создать так называемый функциональный индекс на колонке email. Делается это так:
CREATE INDEX ind_email ON TABLE (LOWER(email));
Функциональный индекс создается не по полю таблицы, а по произвольному выражению и хранит значения результата работы функции, которых фактически может и не быть в таблице. Стоит помнить, что если у вас создан индекс по функции со сложными вычислениями, то и обновление такого индекса будет достаточно затратной операцией с точки зрения вычислительных ресурсов. Также по функциональному индексу будет собираться отдельная статистика. В каких-то случаях будет более рационально переписать запрос, чем создавать функциональный индекс.
3⃣ Приведение к типу данных.
Как правило, у PostgreSQL нет проблем с конвертацией одного типа данных в другой, но в некоторых случаях такая конвертация может привести к неиспользованию индекса. Например, в таком запросе не будет использоваться индекс на колонке id как раз из-за приведения к типу numeric:
SELECT * FROM table WHERE id = 100::numeric;
Следовательно, нужно следить за такими вещами и проверять использует ли PostgreSQL индекс в вашем запросе при приведении к определенному типу данных.
4⃣ SQL оператор не поддерживается выбранным типом индекса.
Одним из таких операторов, например, является ILIKE. Если мы напишем такой запрос:
SELECT * FROM table WHERE email ILIKE example@yandex.ru;
ILIKE является расширением оператора LIKE и не описан в стандарте SQL, это фишка PostgreSQL. ILIKE позволяет нам делать независимый от регистра поиск по заданному шаблону с учетом языковой среды, в которой установлена PostgreSQL. B-tree индекс не поддерживает данный оператор, так что в таком запросе индекс на поле email не будет использован.
Здесь мы рассмотрели варианты почему PostgreSQL НЕ МОЖЕТ использовать индекс, завтра мы с вами рассмотрим варианты, при которых PostgreSQL НЕ ХОЧЕТ использовать индекс, а предпочитать последовательное сканирование, или еще какие-то другие методы сканирования данных.