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

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

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

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

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

9 ответов


общие меры сложности программного обеспечения включают в себя Цикломатическая Сложность (мера того, насколько сложен поток управления) и сложность Холстед (мера сложной арифметики).

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

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

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

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

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

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


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

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

что-то типа:

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

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

вычислить сложность хранимой процедуры TSQL


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


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

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


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

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


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

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


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

SELECT * FROM foo;

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

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

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

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


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

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

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