Есть несколько причин, почему запрос может быть медленным. В любом случае, чтобы действительно увидеть, что делает планировщик запросов, вы должны запустить на нем explain
. Команда explain
в большинстве СУБД скажет вам, какие индексы планирует использовать планировщик запросов, сколько строк данных вы можете ожидать и сколько строк данных необходимо обработать, прежде чем вы начнете получать результаты. назад.
Теперь, чтобы указать некоторые конкретные причины, по которым запрос может выполняться медленно, вы правы относительно индексов. Отсутствие индекса приведет к последовательному сканированию таблиц, которые у вас есть в вашем запросе, что может замедлить работу, если эти таблицы большие. Создание индексов для столбцов, к которым вы присоединяетесь или используете в предложении where, безусловно, помогает. Однако иногда планировщик запросов выполняет плохую работу, и вам нужно будет помочь ему, используя команду 'force', чтобы указать, какой индекс он должен использовать.
Это ошибочное мнение, что присоединение замедляет вещи. Одноуровневые соединения обычно хороши. Например, вы выбираете данные из таблицы A и соединяете B с A и C с A. Соединения с таблицами B и C являются соединениями одного уровня. Многоуровневые объединения занимают больше времени для обработки. Вот почему в хранилищах данных и витринах данных людям нравится использовать звездные схемы; это одна большая таблица с метриками, таблица фактов, к которой выполняется запрос, и есть другие таблицы с описательными данными, таблицы измерений, которые присоединяются к нему. Схемы типа «звезда» избегают многоуровневых объединений, поэтому отчеты могут выполняться быстро.
Денормализация ваших таблиц заманчива, однако я настоятельно рекомендую против этого. Когда вы начнете денормализировать свою базу данных, вы столкнетесь с серьезными проблемами в будущем, если объем данных, которые вы храните, станет очень большим, что приведет к проблемам с масштабированием. Кроме того, ведение денормализованных таблиц требует от ваших инженеров действительно хороших рабочих знаний о схеме, что усложняет техническую задолженность. Конечно, это краткосрочная выгода, но долгосрочная боль означает, что у вас должна быть действительно веская причина, чтобы захотеть это сделать. Сделайте несколько многолетних проектов, которые нужно масштабировать, и вы действительно увидите боль денормализации.
Теперь, в зависимости от ваших потребностей, часто бывает предпочтительнее иметь отдельную базу данных отчетов, витрины данных или хранилище данных, которые создаются и обновляются с использованием данных из вашей производственной базы данных. Это дает вам гораздо больше свободы при разработке схем, которые действительно поддерживают запросы отчетов, которые вы хотите выполнить, и не дает вам взломать вашу производственную базу данных.
Если вам не хватает ресурсов, хорошей альтернативой отдельной базе данных являются временные таблицы. Временная таблица - это таблица, которая существует на протяжении всего времени вашего соединения с базой данных / сеанса. Другие соединения / сеансы не могут видеть или получать к ним доступ, качество изоляции, и вы можете использовать их для хранения и индексации данных, которые вы хотите использовать в более крупном и более сложном запросе. Очень просто использовать, если вы взаимодействуете с базой данных через консоль. Если вы работаете с одним программным способом и имеете пул соединений, я думаю, что вам, возможно, придется отбросить таблицу, когда вы закончите; не могу вспомнить, но уборка никогда не бывает плохой.
Одна из очевидных причин медленного выполнения запроса заключается в том, что вы выбираете большой объем данных. Если вы попытаетесь соединить несколько таблиц, каждая из которых имеет несколько сотен миллионов строк строк (1000), ваша СУБД может начать копаться в виртуальной памяти для выполнения объединений. Даже с индексами, которые могут привести к обмену на вашем диске, и когда это произойдет, добро пожаловать в slowville.
Выбор подвыбора (select a, b, (select c, d from e where e.id = a) from f
) или его использование в предложении where также может быть очень медленным, поскольку этот отбор фактически является запросом, который выполняется для каждой строки данных.Использование подвыбора в объединении не страдает от этой проблемы, тем не менее, вы по существу присоединяетесь к временной таблице без индекса, и в зависимости от того, сколько данных вы получаете с помощью этого подвыбора, это тоже может замедлить работу.
Команда in
также может быть проблематичной, если ваш набор очень большой.Опять же, большой набор - это, в основном, большая временная таблица без индекса, поэтому каждый раз, когда вы проверяете, находится ли конкретное значение в вашем наборе, вы выполняете последовательное сканирование.
Это наиболее существенные причины, по которымЯ могу думать прямо сейчас.Есть и другие, но я думаю, что это выходит за рамки ответа о переполнении стека; -)