Таблица плюсы и минусы ооо и ип: ИП или ООО: отличия, плюсы и минусы

sql — Каковы преимущества/недостатки использования CTE?

A CTE не намного больше, чем синтаксический сахар .
Это повышает читаемость и позволяет избежать повторения .

Думайте об этом как о заполнителе фактического оператора, указанного в предложении WITH() -. Механизм заменит любое появление имени CTE в вашем запросе этим оператором (очень похоже на представление). В этом смысл встроенный .

По сравнению с ранее заполненной таблицей (отложенной или созданной) Вы найдете преимуществ :

  • пригодных для использования в ad-hoc -запросах (функциях, представлениях)
  • отсутствие непредвиденных побочных эффектов (наиболее узкая область применения)

…и недостатки :

  • Вы не можете использовать результат CTE в разных утверждениях
  • Вы не можете использовать индексы и статистику для оптимизации набора CTE (хотя он будет неявно использовать существующие индексы и статистику целевых объектов — если это уместно).

В с точки зрения производительности сохраненный набор (объявленная или созданная таблица) может быть (гораздо!) лучше в некоторых случаях, но это заставляет вас использовать процедурный код. Вам придется гонять своих лошадей , чтобы узнать, какая из них лучше…

Пример: различные подходы к тому же самому

В следующем простом (довольно бесполезном) примере описывается набор пользовательских таблиц вместе с их столбцами. . Я использую разные подходы, чтобы сообщить SQL-серверу, чего я хочу:

Попробуйте это с «включить фактический план выполнения»

 USE master; -- в моем случае в основной базе данных всего 5 «пользовательских таблиц», вы, конечно, можете использовать любую другую БД
ИДТИ
    
--simple join, сначала небольшой набор присоединяется к большому набору
ВЫБЕРИТЕ o.name AS имя_таблицы
      ,c.name AS имя_столбца
ИЗ sys.objects o
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.columns c ON c.object_id=o. object_id
ГДЕ o.type='U';
ИДТИ
--простое соединение "наоборот" с фильтром как часть предложения ON
ВЫБЕРИТЕ o.name AS имя_таблицы
      ,c.name AS имя_столбца
ИЗ sys.columns c
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.objects o ON c.object_id=o.object_id AND o.type='U';
ИДТИ
--подключиться из большого набора с подзапросом к маленькому набору
ВЫБЕРИТЕ o.name AS имя_таблицы
      ,c.name AS имя_столбца
ИЗ sys.columns c
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
    ВЫБЕРИТЕ о.*
    ИЗ sys.objects o
    ГДЕ o.type='U' --пользовательские таблицы
) o ON c.object_id=o.object_id;
ИДТИ
--join для больших и малых с построчным ПРИМЕНЕНИЕМ
ВЫБЕРИТЕ o.name AS имя_таблицы
      ,c.name AS имя_столбца
ИЗ sys.columns c
ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ (
    ВЫБЕРИТЕ о.*
    ИЗ sys.objects o
    ГДЕ o.type='U' --пользовательские таблицы
    И o.object_id=c.object_id
) о;
ИДТИ
--используйте CTE для «предварительной фильтрации» небольшого набора
С тэ КАК
(
    ВЫБЕРИТЕ о.*
    ИЗ sys.objects o
    ГДЕ o.type='U' --пользовательские таблицы
)
ВЫБРАТЬ cte. name AS имя_таблицы
      ,c.name AS имя_столбца
ИЗ sys.columns c
ВНУТРЕННЕЕ СОЕДИНЕНИЕ cte ON c.object_id=cte.object_id;
ИДТИ
 

Теперь посмотрите на результат и планы выполнения:

  • Все запросы возвращают один и тот же результат.
  • Все запросы создают один и тот же план выполнения

Важный совет: На вашем компьютере это может отличаться!

Почему это?

T-SQL является декларативным языком . Ваше заявление представляет собой описание ЧТО вы хотите получить. Это не ваша работа, чтобы сказать двигателю , КАК это делается.

Чрезвычайно интеллектуальный механизм SQL-Server найдет лучший способ получить требуемый набор. В приведенном выше случае все описания результатов указывают на одну и ту же цель. Двигатель может вывести это из различных утверждений и находит один и тот же план для всех из них.

Ну, это дело вкуса?

В некотором роде. ..

Есть несколько важных моментов, о которых следует помнить:

  • У движка нет причин вычислять результат CTE до остальное (хотя оператор может выглядеть так ). Поэтому неправильно описывать CTE как что-то вроде временной таблицы
  • Другими словами: видимый порядок вашего оператора не предсказывает фактический порядок выполнения !
  • Умный движок достигнет своих пределов сложности и уровня вложенности. Представьте себе различные VIEW , использующие CTE и звонящие друг другу…
  • Бывают случаи, когда двигатель действительно глючит. Я помню случай, когда КТР не намного превышал 9.0014 ПОПЫТКА_КАСТ . Идея заключалась в том, чтобы обеспечить допустимые значения в приведенном ниже запросе. Но двигатель подумал «Ой, просто литье, не дорого!» и включил актуальный CAST в план выполнения на более высокую позицию. Я помню другой случай, когда движок выполнял дорогостоящую операцию с миллионами строк (без необходимости конечный результат отфильтровывался до крошечного набора) только потому, что фактический порядок выполнения был не таким, как ожидалось.

Хорошо… Итак, когда мне следует использовать CTE?

Следующие пункты являются вескими причинами для использования CTE:

  • CTE может помочь вам избежать повторяющихся подзапросов.
  • CTE может использоваться несколько раз в вашем операторе, например. внутри JOIN с динамическим поведением в зависимости от фактического количества строк.
  • Вы можете использовать несколько CTE в одном операторе, а также использовать результат одного CTE в более позднем CTE.
  • Существуют рекурсивные (или лучше итеративные ) CTE.
  • Иногда я использовал однострочный -CTE для определения/предварительного вычисления переменных , которые позже используются в запросе. Что бы вы сделали с объявленными переменными в процедурном T-SQL. Вы можете использовать A CROSS JOIN , чтобы легко ввести их в свой запрос.
  • , а также очень приятно: обновляемый CTE позволяет очень легко читать операторы, то же самое относится к DELETE .
    То же, что и выше: Ничего нельзя было сделать без CTE, но гораздо лучше читать (мне очень нравится говорящих имён ).

Заключительные советы

Что ж, бывают случаи, когда некрасивый код работает лучше 🙂

Всегда хорошо иметь чистый и читаемый код. CTE поможет вам в этом. Так что попробуйте. Если производительность плохая, углубитесь в детали, посмотрите на планы выполнения и попытайтесь найти причину, по которой движок может принять неправильное решение.

В большинстве случаев пытаться перехитрить двигатель с помощью таких подсказок, как FORCE ORDER (но может помочь) — плохая идея.0012

ОБНОВЛЕНИЕ

Меня попросили конкретно указать преимущества и недостатки:

Хм, технически нет реальных преимуществ или недостатков . Не считая рекурсивных CTE , нет ничего, что нельзя было бы решить без CTE.

Преимущества
Основным преимуществом является читаемость и ремонтопригодность .
Иногда CTE может сэкономить сотни строк кода. Вместо повторения огромного подзапроса можно использовать просто имя в качестве переменная . Исправления в подзапросе могут быть решены только в одном месте.
CTE может использоваться в специальных запросах и облегчать вашу жизнь.

Недостатки
Одним из возможных недостатков является то, что даже опытным разработчикам очень легко принять CTE за временную таблицу, предположить, что видимый порядок шагов будет таким же, как реальный порядок выполнения, и споткнуться в неожиданные результаты или даже ошибки .
И — конечно 🙂 — странная неправильный синтаксис ошибка, которую вы увидите, когда будете писать CTE после другого оператора без разделителя ; . Вот почему многие люди склонны использовать .

firebird — плюсы и минусы различных схем для таблиц, которые связаны с одним элементом данных

спросил

Изменено
11 лет, 11 месяцев назад

Просмотрено
522 раза

Я разрабатываю систему с базой данных. Я намереваюсь, чтобы у каждой таблицы был PK, который является произвольным, сгенерированным и поддерживаемым системой.

Моя среда (для разработки и производства) — Windows 7; Делфи; и встроенная база данных (вероятно, Firebird).

В мои структуры данных входит одна таблица OWNER, с которой связано очень мало информации — возможно, не больше, чем имя и описание. Остальная часть структуры данных будет состоять примерно из 50 таблиц, каждая с именем и описанием, а также со списком других атрибутов — скажем, в среднем по 20 на таблицу. Кроме того, может быть 20 ассоциативных таблиц, большинство из которых будут иметь только атрибуты FK, хотя небольшая часть будет иметь дополнительные атрибуты. Я намерен (по крайней мере, для начала) полностью нормализовать схему. 93). Большинство доступов, скорее всего, будет кластеризованным — будет значительное количество доступов для одного ВЛАДЕЛЬЦА, а затем значительное количество доступов для другого ВЛАДЕЛЬЦА.

Каждый элемент данных будет принадлежать только одному ВЛАДЕЛЬЦУ и не может быть передан от ВЛАДЕЛЬЦА к ВЛАДЕЛЬЦУ. Все обращения к базе данных будут знать, какого ВЛАДЕЛЬЦА они используют; никакой доступ никогда не будет иметь доступ к содержимому более чем одного ВЛАДЕЛЬЦА.

Мне известны следующие три варианта разработки моей схемы:

  1. Используйте таблицу OWNER, как описано. Используйте OWNER PK в качестве внешнего ключа в каждой таблице (но, возможно, не в ассоциативных таблицах). Добавьте OWNER PK в качестве дополнительного предложения в каждый запрос, соединение, хранимую процедуру, представление и т. д.
  2. Добавьте в таблицу OWNER столбец, содержащий небольшой код, скажем, четырехзначное целое число. Для каждого ВЛАДЕЛЬЦА создайте повторяющийся набор таблиц — имена таблиц для конкретного ВЛАДЕЛЬЦА будут иметь соответствующий код, добавленный в качестве суффикса. Это потребовало бы, чтобы каждый доступ предварительно получил код суффикса из базы данных. Тогда доступ будет к соответствующему набору таблиц.
  3. Для каждого ВЛАДЕЛЬЦА создать дублированную базу данных с дублирующимися таблицами и именами таблиц. Это означает, что, вероятно, будет иметься вспомогательная общая база данных, содержащая данные о соответствующей дублирующей базе данных. Опять же, эта общая база данных потребует доступа перед любым доступом — или серией доступов для одного конкретного ВЛАДЕЛЬЦА.

Каковы плюсы и минусы этих разных подходов? Я пропустил какие-либо другие варианты общего дизайна?

Редактировать наоборот — вместо этого я предоставил свой собственный ответ.

  • дизайн базы данных
  • firebird
  • схема базы данных

3

Вариант №1, безусловно, лучший. Очевидно, вы планируете использовать сгенерированный системой идентификационный номер для этой записи… в противном случае вы столкнетесь с проблемой, если ваш OWNER pk является именем человека, и вы получите несколько John Smith.

Вариант №2 подойдет, но слишком усложняет. Пока у вас уже есть OwnerId в качестве PK в таблице OWNER, просто используйте его для остальных и сэкономьте дополнительные накладные расходы и усилия.