Re[15]: Бизнес логика в ХП
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.06.16 17:17
Оценка:
Здравствуйте, Gattaka, Вы писали:

G>Вот запрос:

  Запрос
G>

G>    -- 1. Простовляем списку узлов новую роль
G>        update Network_Node
G>    set Property = true -- Некий признак, флаг, роль и т.п. не вдаемся в подробности. Нам пока не важно.
G>    where Id in (select Id from @selectedNodes) --В хранимку приходит список идентификаторов выбранных пользователем узлов - табличная переменная @selectedNodes

G>    -- 2. В соответсвии с бизнес логикой нужно найти связать сетевые узлы, которым мы проставили роль по связям зарегестрированных на них пользователей 
G>    --    
G>    insert Node_Node(Node1Id, Node2Id)
G>    select distinct n.Id, un2.NodeId
G>    from Network_Node n
G>    join UserOnNode un1 on un1.NodeId = n.Id     -- Берем пользователей зарегестрированных на узле
G>        join User_User uu on uu.User1Id = un1.UserId -- Берем связи пользователя
G>        join UserOnNode un2 on un1.UserId = uu.User2Id -- Берем узлы на котором зарегестрирован связанный пользователь
G>    where n.Property = true 
G>          and not exists(select * from Node_Node nn3 where nn3.Node1Id = n.Id and nn3.Node2Id = un2.NodeId) -- такая связь еще не сущетвует

G>


Кстати в запросе ошибка, смотри третий джоин


G>Итак, напомню

G>

G>В таблице User(Id, Name) 70000 записей. В таблице Network_Node(Id, Name, Property) 70000 записей. В Таблице UserOnNode(NodeId, UserId) — 70000 записей по одному пользователю на узле. В таблице User_User(User1Id, User2Id) — связи пользователей, все польователи связаны со всеми — это 70000*70000=4900000000 записей. На каждую из записей по 8 байт, т.е. приблизительно 36 гигабайт табличка, не учитывая индексов. Теперь в таблице Network_Node(Node1Id, Node2Id) — связи узлов. Допустим кто-то с кем-то уже был связан в случайном порядке 900000000 записей каких-то.
G>Нам нужно сделать: У узлов (35000 каких-то) Network_Node меняется свойство Property — бизнес логика такова, что нужно найти зарегестрированные на этих узлах пользовати и если они связаны — добавить связи по узлам.


Если все пользователи связаны со всеми, то установка property на любом узле приведет к добавлению Node_Node всех узлов в поле Node2Id. Что для дальнейшего использования не имеет смысла, так как просто можно запрашивать n.Property вместо джоина к Node_Node.

А если ты приведешь реальные средние значения количества связей User_Node и User_User, то перемножив два числа получим количество считываемых\добавляемых строк. Например для User_Node примерное соотношение 10, а для User_User — 150, то надо будет получить максимум 1500 записей для каждого ID. Размер записи — 8 байт (два ID по 4 байта). То есть 12кб. Если это операция обновления, которая не выполняется 10 раз в секунду, то можно не беспокоиться о скорости.

А вообще я бы лучше сделал материализованную view вида

create view UserNodeJunction with schemabinding as 
select 
    un1.NodeId as Node1Id, 
    un1.UserId as User1Id, 
    un2.NodeId as Node2Id, 
    un2.UserId as User2Id 
from UserOnNode un1 
join User_User uu on uu.User1Id = un1.UserId -- Берем связи пользователя
join UserOnNode un2 on un2.UserId = uu.User2Id 


create clustered index PK_UserNodeJunction on UserNodeJunction (Node1Id, User1Id, Node2Id, User2Id)
create index IX_NodeLink on UserNodeJunction (Node1Id, Node2Id)


Тогда твой запрос вообще можно было бы во view превратить:
create view NodeWithProperty as 
select distinct n.Id, j.Node2Id
from Network_Node n
join UserNodeJunction j on n.Id = j.Node1Id
where n.Property = true


И если это view индексировать (вытащив distinct на уровень выше), то вовсе пропадет необходимость что-то куда-то вставлять.

ЗЫ. Тем не менее я понял твою идею — тяжелую логику держать на уровне SQL, а не тащит в приложение. И я с этим согласен. Но средства ты кардинально не те выбрал, как на уровне базы, так и на уровне приложения. Поэтому ничего толком обосновать не можешь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.