С Новым годом! Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,765

Возможно ли обойтись без вспомогательной таблицы?

13.12.2024, 09:30. Показов 1026. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть таблица с иерархическими записями:
T-SQL
1
2
3
4
5
6
7
8
9
10
create table smp
(
    smp_id int not null,
    master_smp_id int null,
    descr nvarchar(42) null,
 
    constraint pk_smp primary key clustered (smp_id)
);
 
create nonclustered index ix_smp_master_smp_id on smp (master_smp_id asc);
И есть запрос, который сначала по исходной таблице собирает информацию обо всех предках каждой записи и потом для каждой исходной записи собирает какую-то вычисляемую информацию по всем её предкам:
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
with smp_hierarchy as
(
    select 
          smp_id
        , smp_id as ancestor_id 
    from 
        smp
    
    union all
    
    select
          smp.smp_id
        , smp.master_smp_id as ancestor_id
    from 
        smp
    join 
        smp_hierarchy 
             on smp_hierarchy.ancestor_id = smp.smp_id
            and smp.master_smp_id is not null
)
select 
    smp.*
    smp_ext.*
from 
    smp
outer apply
(
    select
        sum(smp_hierarchy.ancestor_id) as some_calc_data
    from 
        smp_hierarchy
    where 
        smp_hierarchy.smp_id = smp.smp_id
    group by
        smp_hierarchy.smp_id
) as smp_ext
Но работает медленно.

В плане запроса при этом восклицательным знаком подсвечиваются два блока, с уведомлением, что используется 'tempdb'. Хотя, если я правильно понимаю цифры из плана, именно эти блоки не отнимают слишком много ресурсов (cost: 1-2%):
Operator used tempdb to spill data during execution with spill level 2 and 1 spilled thread(s); Hash wrote 888 pages to and read 888 pages from tempdb with granted memory 1088KB and used memory 1032KB
Если вместо рекурсивного запроса, формирующего 'smp_hierarchy', использовать предварительно заполненную и проиндексированную реальную таблицу 'smp_hierarchy (smp_id, ancestor_id)', то работает в десятки раз быстрее, но вот поддерживать эту таблицу та ещё морока, т.к. приходится её перестраивать при любом добавлении/удалении записи и при любом изменении master_id в исходной таблице.

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

Почитал про 'hierarchyid', но это, если я правильно понял, просто вариант замены 'master_smp_id' на особый тип поля. И для выполнения обозначенного выше запроса мне всё равно придётся предварительно составлять список всех предков для каждой записи (и оформлять его в виде виртуальной или реальной таблицы).
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.12.2024, 09:30
Ответы с готовыми решениями:

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

Возможно ли обойтись без XPath
На этой страничке http://www.onliner.by/#login есть форма для входа. Код полей ввода такой: <input type="text"...

Возможно ли обойтись без циклов, используя сложный запрос с динамическими параметрами?
Я новичёк в C++ builder,а так же не большие познания в sql. О коде который ниже:выборка происходит из несольких таблиц,потом вставляется...

13
668 / 291 / 120
Регистрация: 12.04.2022
Сообщений: 1,000
13.12.2024, 09:50
Цитата Сообщение от kotelok Посмотреть сообщение
использовать предварительно заполненную и проиндексированную реальную таблицу

Постройте view with schemabinding + индексы вместо таблички

T-SQL
1
2
3
4
5
6
7
8
create view smp  with schemabinding
(
    smp_id int not null,
    master_smp_id int null,
    descr nvarchar(42) null,
 
    constraint pk_smp primary key clustered (smp_id)
);
1
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
13.12.2024, 09:57
Цитата Сообщение от PaulWist Посмотреть сообщение
Постройте view with schemabinding
приветствую!
Расскажите, пожалуйста, в чём профит? Я видел такое только в рамках таблиц и ХП, оптимизированных для памяти.
0
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,765
13.12.2024, 10:11  [ТС]
Цитата Сообщение от PaulWist Посмотреть сообщение
Постройте view with schemabinding
Не, не получается.

Чтобы добавить индекс на View, надо сначала добавить ему уникальный кластеризованный индекс.
Cannot create index on view 'smp_hierarchy_view'. It does not have a unique clustered index.
The first index created on a view must be a unique clustered index. After the unique clustered index has been created, you can create more nonclustered indexes.
https://learn.microsoft.com/en... exed-views
А уникальный кластеризованный индекс в данном случае не добавить, т.к. их нельзя добавлять на view, в которых CTE используется (а как без CTE получить тот же результат я пока не знаю):
Cannot create index on view because it references common table expression "smp_hierarchy". Views referencing common table expressions cannot be indexed. Consider not indexing the view, or removing the common table expression from the view definition.
0
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
13.12.2024, 11:33
Цитата Сообщение от Jack Famous Посмотреть сообщение
Расскажите, пожалуйста, в чём профит?
кажется, это материализованное представление. И тогда я ещё больше не понимаю, в чём смысл, если можно просто сделать таблицу…

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

UPD:
Цитата Сообщение от Jack Famous Посмотреть сообщение
кажется, это материализованное представление
индексированное. Думал, это одно и то же, ан нет)

UPD2:
Цитата Сообщение от Jack Famous Посмотреть сообщение
индексированное. Думал, это одно и то же, ан нет)
грёбаные мелкомягкие. Совсем запутали. MATERIALIZED VIEW только для Azure Synapse Analytics. Так что да — это материализованное (оно же индексированное) представление (с кучей ограничений по созданию/возможностям). И не забыть With (NoExpand) при использовании.
0
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,765
13.12.2024, 11:49  [ТС]
Цитата Сообщение от Jack Famous Посмотреть сообщение
настроил бы синхронизацию
Сейчас так и сделано - есть таблица с иерархическими записями, есть "плоская" таблица (с индексами), в которой, по сути, лежит то же, что выдаёт рекурсивный запрос.

И есть триггеры на исходной таблице (insert/update/delete), в рамках которых "плоская" таблица поддерживается в согласованном состоянии. Вот попытался уйти от этой сложной логики, но достаточно быстрого варианта пока не нашёл.
0
668 / 291 / 120
Регистрация: 12.04.2022
Сообщений: 1,000
13.12.2024, 12:32
Цитата Сообщение от kotelok Посмотреть сообщение
Не, не получается.
Блин, зарапортовался ... виноват, склероз

У вас нормальное решение, чем оно не устраивает? долго дерево перестраивается?

Когда-то TaPaK говорил, что используется развернутая табличка для дерева

у нас вторая таблица аля ParentId | ChildId где для каждого вашего ID = 1 будет 3 записи 1-1 1-2 1-3

Цитата Сообщение от Jack Famous Посмотреть сообщение
Расскажите, пожалуйста, в чём профит?
schemabinding + кластерный индекс на view позволяет/создаёт табличку (определенную во view) на диске, те хранится результат запроса, + доп. бонус, если Engeen видит, что где-то используется запрос повторяющий определение view, то обращение идёт к view В следующих двух запросах показано, как можно использовать индексированное представление, даже если представление не указано в предложении FROM .
1
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
16.12.2024, 10:31
PaulWist, всё равно непонятно…

1. У ТСа иерархическая табличка.
2. Он собирает из неё данные по по всем предкам. Это работает долго.
3. Если иметь табличку на основе иерархической, но "плоскую" то всё летает. Проблема в поддержке такой вспомогательной таблицы.

Индексированное представление — это вычисленный запрос. То есть, можно заранее, например, сгруппировать данные в исходной таблицы и это вычисленное состояние будет доступно на диске. Плюс, оно само будет актуализироваться на основе всех задействованных источников при их изменении. Это удобно. Платим за это удобство увеличением времени изменения источников.

Но главная проблема в огромном количестве ограничений таких индексированных преставлений — в них запрещено практически всё. Именно поэтому я не понимаю, как такая вьюха поможет ТСу, ведь сделать её в виде плоской таблицы на основе иерархии не представляется возможным. Во всяком случае, я не понимаю, как.

Я бы написал ХП для Delete/Insert/Update иерархической таблички и встроил в неё параллельное изменение плоской таблицы. Если уж от иерархии избавиться по каким-то причинам нельзя.
Можно, конечно. и на триггерах построить, но, один хрен, придётся (уже) вычислять (а не иметь на входе), какие данные изменились и производить параллельные правки плоской.

Ссылка на справку со скрином ограничений
0
668 / 291 / 120
Регистрация: 12.04.2022
Сообщений: 1,000
16.12.2024, 12:33
Цитата Сообщение от Jack Famous Посмотреть сообщение
3. Если иметь табличку на основе иерархической, но "плоскую" то всё летает. Проблема в поддержке такой вспомогательной таблицы.
Пока ТС не написал, что конкретно "плохо" при поддержании плоской таблицы.

Цитата Сообщение от Jack Famous Посмотреть сообщение
Но главная проблема в огромном количестве ограничений таких индексированных преставлений — в них запрещено практически всё.
У ТСа формирование рекурсии занимает много времени, т.е. ему рекурсивная вьюха (конечно если бы это было возможно) нужна только для выборки, поэтому все ограничения в общем случае не важны.

Цитата Сообщение от Jack Famous Посмотреть сообщение
Я бы написал ХП для Delete/Insert/Update иерархической таблички и встроил в неё параллельное изменение плоской таблицы. Если уж от иерархии избавиться по каким-то причинам нельзя.
Можно, конечно. и на триггерах построить, но, один хрен, придётся (уже) вычислять (а не иметь на входе), какие данные изменились и производить параллельные правки плоской.
Опять же, мы не знаем как табличка изменятся (OLAP/OLTP) с какой периодичностью, ТС использует плоскую табличку - его устраивает.
0
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,765
16.12.2024, 13:05  [ТС]
Цитата Сообщение от PaulWist Посмотреть сообщение
Опять же, мы не знаем как табличка изменятся
Иерархическая таблица с пользовательскими данными. Пользователи, через API, читают, добавляют, редактируют и удаляют данные (в т.ч. у любой записи может измениться 'master_id').

При этом информация обо всех предках записи нужна при любой CRUD-операции (в т.ч. при считывании коллекции по условию). И информация должна быть актуальной в любой момент времени, потому поддерживать "плоскую" таблицу в согласованном состоянии приходится через триггеры исходной таблицы (а не актуализировать раз в час/сутки по расписанию).

Ну и просто есть сомнения, насколько адекватно в триггере на, скажем, редактирование записи, реализовывать достаточно тяжёлую логику анализа/модификации другой таблицы.
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
16.12.2024, 13:24
Ограничения на глубину есть?
0
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,765
16.12.2024, 13:36  [ТС]
Цитата Сообщение от Аватар Посмотреть сообщение
Ограничения на глубину есть?
В явном виде нет. Но с точки зрения логики предметной области, наверное, можно допустить определённую максимальную вложенность в пределах пары десятков уровней.
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
16.12.2024, 14:02
это много

Добавлено через 7 минут
Цитата Сообщение от kotelok Посмотреть сообщение
Но работает медленно
ну рекурсия же, циклическое выполнение запроса, временные таблицы, предполагаю что без индекса, но это нужно посмотреть. хотя индекс скорее всего и не к месту - много обновлений в цикле. она по определению не родная для sql, а принудительно внедренная. если сделать процедуру с курсорами и циклами, то наверняка еще хуже будет
0
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
16.12.2024, 14:43
Цитата Сообщение от kotelok Посмотреть сообщение
потому поддерживать "плоскую" таблицу в согласованном состоянии приходится через триггеры исходной таблицы
триггеры дают все 3 набора строк: Delete, Insert, Update(As Delete+Insert).
Анализируя эти наборы можно точечно и быстро актуализировать плоскую.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.12.2024, 14:43
Помогаю со студенческими работами здесь

Возможно ли переделать код этой программы так, чтобы обойтись без функции?
Здравствуйте Возможно ли переделать код этой программы так, чтобы обойтись без функции? uses Crt; var x: real; function...

Возможно ли множество без таблицы?
Приветствую. С помощью такого запроса можно получить результат с одной строчкой: SELECT 1 AS 'VIRTUAL_ROW'; Возможно ли...

Возможно ли одним sql обойтись
Доброго дня, стоит передо мной задачка вытащить родителей и их детей в одну строку. Попробую изобразить связь ихнию, можно ли...

С вспомогательной функции произведите сортировку массива по убыванию. С вспомогательной функц
Пример 1. Написать программу сортировки по возрастанию заданного массива случайных чисел, равномерно распределенных в интервале , с помощью...

Верстка таблицы с отступами между строк, но без border-collapse: separate возможно?
Приветствую! Недавно занимаюсь версткой, что то знаю что то нет, так что не серчайте. В общем суть такая нужно сверстать ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru