Подтвердить что ты не робот

Измерение сложности операторов SQL

Сложность методов в большинстве языков программирования может быть измерена в цикломатической сложности с помощью статических анализаторов исходного кода. Существует ли подобный показатель для измерения сложности SQL-запроса?

Достаточно просто измерить время, необходимое для возврата запроса, но что, если я просто хочу количественно оценить, насколько сложен запрос?

[Edit/Note] Хотя получение плана выполнения полезно, это не обязательно то, что я пытаюсь определить в этом случае. Я не ищу, насколько сложно серверу выполнить запрос, я ищу показатель, который показывает, насколько сложно разработчику было написать запрос, и насколько вероятно, что он содержит дефект.

[Редактировать/Примечание 2] Следует признать, что бывают случаи, когда измерение сложности бесполезно, но бывают и такие времена. Для дальнейшего обсуждения этой темы см. этот вопрос.

4b9b3361

Ответ 1

Общие меры сложности программного обеспечения включают Cyclomatic Complexity (мера того, насколько сложным является поток управления) и сложность Halstead (мера сложной арифметики).

"поток управления" в SQL-запросе лучше всего связан с операциями "и" и "или" в запросе.

"Сложность вычислений" лучше всего связана с операторами, такими как SUM или неявные JOINS.

Как только вы решите классифицировать каждую единицу синтаксиса SQL-запроса относительно того, является ли это "потоком управления" или "вычислением", вы можете прямо вычислить измерения Cyclomatic или Halstead.

Что делает оптимизатор SQL для запросов, я думаю, абсолютно не имеет значения. Цель мер сложности - описать, насколько трудно человеку понять этот запрос, а не как эффективно его оценивать.

Аналогичным образом, то, что говорит DDL или вовлечено в него, не должно включаться в такие меры сложности. Предположение, лежащее в основе этих показателей, заключается в том, что сложность машин внутри используемой абстракции не интересна, когда вы просто вызываете ее, потому что, по-видимому, абстракция делает что-то, что хорошо понимает кодер. Вот почему Halstead и Cyclomatic меры не включают подзапросы в их подсчете, и я думаю, вы можете сделать хороший пример, что представления и DDL-информация - это те, которые вызываются "абстрактными".

Наконец, как совершенно правильно или как совершенно неправильно эти числа сложности не имеют большого значения, так как они отражают некоторую правду о сложности, и вы можете сравнивать их по отношению друг к другу. Таким образом, вы можете выбрать, какие фрагменты SQL являются самыми сложными, поэтому сортируйте их все и сосредоточьте внимание на тестировании на самых сложных.

Ответ 2

Я не уверен, что поиск планов запросов ответит на вопрос: планы запросов скрывают часть сложности вычисления, выполненного над данными, прежде чем он будет возвращен (или использован в фильтре); в запросах требуются значимые базы данных. На самом деле сложность и продолжительность выполнения несколько противоположны; что-то вроде "Хорошо, быстро, дешево - выберите любые два".

В конечном счете это о шансах совершить ошибку или не понимать код, который я написал?

Что-то вроде:

  • количество таблиц раз (1
  • +1 за одно выражение объединения (+1 за внешнее соединение?)
  • +1 за предикат после WHERE или HAVING
  • +1 за GROUP BY выражение
  • +1 за UNION или INTERSECT
  • +1 за вызов функции
  • +1 за CASE выражение
  • )

Ответ 4

SQL-запросы являются декларативными, а не процедурные: они не указывают, как достичь своей цели. Механизм SQL создаст процедурный план атаки, и это может быть хорошим местом для поиска сложности. Попробуйте изучить вывод инструкции EXPLAIN (или EXPLAIN PLAN), это будет грубое описание шагов, которые двигатель будет использовать для выполнения вашего запроса.

Ответ 5

Ну, я не знаю ни одного инструмента, который бы делал подобное, но мне кажется, что то, что усложняло бы запрос, было бы измерено: количество объединений число условий количество функций количество подзапросов количество отливок для разных типов данных количество заявлений о случаях количество циклов или курсоров количество шагов в транзакции

Однако, хотя верно, что более сложные запросы могут казаться наиболее вероятными дефектами, я обнаружил, что простые, скорее всего, содержат дефекты, поскольку они, скорее всего, будут написаны кем-то, кто не делает Не понимаю модель данных и, следовательно, они могут работать корректно, но фактически возвращают неверные данные. Поэтому я не уверен, что такая метрика вам много расскажет.

Ответ 6

Хорошо, если вы используете SQL Server, я бы сказал, что вы должны посмотреть на стоимость запроса в плане выполнения (в частности, стоимость поддерева).

Здесь - ссылка, которая затрагивает некоторые вещи, которые вы должны посмотреть в плане выполнения.

Ответ 7

В зависимости от вашей РСУБД могут быть инструменты плана запроса, которые могут помочь вам проанализировать шаги, которые RDBMS возьмет на выбор вашего запроса.

SQL Server Management Studio Express имеет встроенный план выполнения запросов. У Pervasive PSQL есть свой поисковый запрос. DB2 имеет похожие инструменты (забыл, что они называются).

Ответ 8

Хороший вопрос. Проблема в том, что для SQL-запроса вроде:

SELECT * FROM foo;

сложность может зависеть от того, что такое "foo" и от реализации базы данных. Для функции типа:

int f( int n ) {
   if ( n == 42 ) {
      return 0;
   }
   else {
      return n;
   }
}

нет такой зависимости.

Тем не менее, я думаю, что для SELECT можно было бы придумать некоторые полезные показатели, даже если они не очень точны, и мне будет интересно узнать, какие ответы на них будут получены.

Ответ 9

В отсутствие каких-либо инструментов, которые сделают это, прагматичный подход будет заключаться в том, чтобы анализируемые запросы последовательно отформатировались и затем подсчитывали строки кода.

В качестве альтернативы можно использовать размер запросов в байтах при сохранении в файле (при условии, что все запросы сохраняются с использованием той же кодировки символов).

Не блестящий, но разумный прокси для сложности в отсутствии чего-то еще, что я думаю.

Ответ 10

Достаточно разумно считать сложность такой, какой она была бы, если бы вы сами закодировали запрос. Если таблица имеет N строк, то

  1. Простой SELECT будет O (N)
  2. ORDER BY - O (NlogN)
  3. СОЕДИНЕНИЕ - это O (N * M)
  4. DROP TABLE - O (1)
  5. ВЫБЕРИТЕ ОТЛИЧИЕ O (N ^ 2)
  6. Запрос 1 NOT IN/IN Query 2 будет O (O 1(N) * O 2(N))