|
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
|
||||||
.NET 4.x Как опитмально поступить в передаче состояния у наследников (foreignkey)03.06.2021, 08:59. Показов 4261. Ответов 55
Всем доброе утро!!!
Представим вот такую задачу. Есть некая онлайн школа допустим программирования. В ней есть несколько курсов по разным ЯП (таблица Course). Есть студенты (таблица Student), которые могут состоять ТОЛЬКО в одном курсе. То есть ТОЛЬКО один язык. В кажом курсе может быть до 1000 студентов. Есть структура базы
У каждого студента есть свой статус/состояние учёбы в этом курсе. Статусов ограниченное количество, поэтому они вынесены в код C# в enum, а в базу передаётся только число этого enum для оптимизации работы БД. Допустим Принят = 0, Сдал = 1, Должник = 2, Не Сдал = 3, Отсутствовал = 4, Так вот задача. В таблицу Course нужно передавать статус от всех студентов. Вот что я имею в виду: Есть курс "Программирование C#". Есть 2 студента в этом курсе. Вася со статусом "Не Сдал" = 3 Петя со статусом "Сдал" = 1 Нужно установить статус курсу, по самому безотвественному студенту, так как курс не может быть закрыт/закончен (со статусом "Сдал" = 1) до тех пор пока хоть один студент находится в другом состоянии. Логика должна быть примерно такая: Если в курсе есть хоть один студент (Student.Status) который в статусе Отсутствовал = 4, то и в Course.Status должно быть Отсутствовал = 4. Если есть хоть один Student.Status Не Сдал = 3, то и в Course.Status должно быть Не Сдал = 3. Если есть хоть один Student.Status Должник = 2, то и в Course.Status должно быть Должник = 2. Если есть хоть один Student.Status Сдал = 1, то и в Course.Status должно быть Сдал = 1. Если есть хоть один Student.Status Принят = 0, то и в Course.Status должно быть Принят = 0. Данные в таблице по студентам обновляются каждый час. То есть каждый час, после обновления таблицы Student нужно проверять статусы наследников, и устанавливать новые статусы в таблицу Course. Данных в таблице (Student) будет более 10млн. И данных в таблице (Course) будет больше 1млн. Как это сделать с минимальной выгрузкой всех данных в программу? Или ещё лучше как сформировать запрос SQL чтобы это всё происходило на стороне СУБД, без получения данных в программу. Или может SQL запрос который получает полуобработанные данные вида: CourseId - Status(уже проверенный) Или может уже существует подход к такой задаче. p.s. Используется MySQL база и библиотека linq2db.
0
|
||||||
| 03.06.2021, 08:59 | |
|
Ответы с готовыми решениями:
55
Фильтрация ForeignKey поля по другому ForeignKey полю в админке Как добавить ключ FOREIGNKEY в таблицу?
|
|
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
|
|||
| 03.06.2021, 18:40 | |||
|
1
|
|||
|
Модератор
|
||
| 03.06.2021, 19:04 | ||
|
Как в таком случае сервер будет их обрабатывать без таблицы Статус-Приоритет?
1
|
||
|
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
|
|
| 03.06.2021, 19:29 | |
|
Элд Хасп, "Статусов" всего пять. Почему бы сразу не выстроить их по приоритетам ? Тем более, что в интерфейсе вместо статусов будет отображаться из смысловой эквивалент - текст.
Зачем городить огород ради одной грядки, то бишь вытащенного с потолка "приоритета" ?
1
|
|
|
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
|
|||||||
| 03.06.2021, 22:49 [ТС] | |||||||
|
Данные периодически будут добавляться (Insert) не только (Update). Итого минимум данных в таблице (Student) будет более 10млн. И данных в таблице (Course) будет больше 1млн. Со временем максимум планируется (может за год) (Student) около 30млн. И (Course) около 15млн. Программы-клиенты, которые будут использовать базу, чаще всего будут получать данные именно из таблицы Course. И если каждый раз при получении пересчитывать статус от Student то будет слишком накладно. Вот поэтому думаю, что лучше статус присвоить при самом получении изменений в Student. Таблицу Student программы клиенты будут использовать редко. А Course часто. Статусов не пять, их гораздо больше. Нельзя использовать вычисление по возрастанию. (это только в примере) На текущий момент нужна определённая передача статусов от Student к Course. В дальнейшем добавятся дополнительные, или заказчик скажет, что нужно изменить логику, и присваивать с другими приоритетами. То есть к порядковому числу enum привязываться категорически нельзя. И приоритет там не с потолка. Смотрю в сторону триггеров, но к сожалению ещё с ними не работал (
0
|
|||||||
|
Модератор
|
||
| 03.06.2021, 23:16 | ||
|
При изменении таблицы Студентов хранимые процедуры будут вносить изменения в эту таблицу. Тогда программа-клиент может просто запросить все статусы этого курса и локально обработать их как ей нужно. Будет гораздо проще извлечь любую требуемую информацию. Чем потом под каждый вероятный вид запроса придумывать как его оптимально сделать и, возможно, менять структуру БД.
1
|
||
|
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
|
||
| 03.06.2021, 23:35 | ||
|
ХП, вызываемая триггером изменения-добавления "студента", просто извлекает статус из "курса" этого "студента", заодно получая "приоритет". "Приоритеты" "студента" и "курса" сравниваются и, если возникает потребность замены "статуса" в "курсе", выполняется апдейт "курса. Никаких min, три короткие операции : 1) извлечение "приоритета" из "статуса" "студента" (1 запись), 2) извлечение из двух связанных таблиц "курсов" и "справочника приоритетов" действующего "приоритета" и, возможно, 3) апдейт "статуса" в таблице "курсов".
1
|
||
|
14371 / 9478 / 1360
Регистрация: 21.01.2016
Сообщений: 35,752
|
||
| 04.06.2021, 05:52 | ||
|
Я вот из обсуждения не понял на кой тут нужен триггер, который будет срабатывать при каждой вставке строки для вычисления данных, которые понадобятся раз в хрен знает сколько?
Такие вещи нужно вычислять только когда они реально нужны, а не на каждый чих. Если такие запросы более-менее частые, а актульностью данных можно немного поступиться, то можно завести summary table, куда временно складывать результаты вычислений. Но триггер для этого внатуре перебор.
1
|
||
|
Модератор
|
|||
| 04.06.2021, 06:48 | |||
|
Такое обновление (Update + Insert) - это одна операция (транзакция) или нет? И можно ли в БД вызвать автообновление связанных данных не вовремя этой операции, а после неё? Или такое автообновление должно быть вызвано внешним кодом (как изначально и предполагал TC)?
1
|
|||
|
14371 / 9478 / 1360
Регистрация: 21.01.2016
Сообщений: 35,752
|
|||
| 04.06.2021, 07:12 | |||
|
Вообще, я крайне против триггеров. Только когда иначе ну совсем никак, тогда только допускаю их использование.
1
|
|||
|
Модератор
|
||
| 04.06.2021, 07:19 | ||
|
По крайней мере я так понял. Добавлено через 1 минуту Исходя из топика, вопрос TC был такой: Как после обновления БД оптимально составит SQL запрос по обновлению связанных данных, чтобы минимизировать выгрузку данных из БД.
1
|
||
|
14371 / 9478 / 1360
Регистрация: 21.01.2016
Сообщений: 35,752
|
|||
| 04.06.2021, 08:18 | |||
|
1
|
|||
|
Модератор
|
||
| 04.06.2021, 08:24 | ||
|
Ну, так я понял из объяснений. Идёт пакетное обновление очень большого количества записей - то есть может занимать какое-то время хотя бы просто на передачу данных. После этого обновления в БД связанных данных - тоже какое-то время. Тем более что счёт идёт на миллионы засей. И всё это время данные в БД могут быть не в полной мере корректными.
1
|
||
|
14371 / 9478 / 1360
Регистрация: 21.01.2016
Сообщений: 35,752
|
||
| 04.06.2021, 08:29 | ||
|
1
|
||
|
Модератор
|
||
| 04.06.2021, 08:30 | ||
|
Только в них. И как я понял по дальнейшим разъяснениям BeginnerCoderCS, нужный статус (приоритетность?) по сути определяется динамически. Вот насколько динамически - он уже не уточнил. Если однократно при обновлении БД (раз в час), то, наверное, нужна какая-то таблица приоритетов. Если нужна возможность каждому клиенту самому определять какую информацию ему запрашивать, то лучше сделать таблицу Курс-Статус-Количество. Статусов много. Но это "много" от силы 10-20. Поэтому вернуть клиенту по запросу такую небольшую табличку - это совершенно не затратно. А уже в клиенте он пусть как хочет её вертит. BeginnerCoderCS, уточните пожалуйста этот момент.
0
|
||
|
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
|
||||||||||||
| 04.06.2021, 08:32 [ТС] | ||||||||||||
|
Вот и выходит, что лучше после одновления, сразу пересчитать все статусы. А получение программой-клиентом этих данных (как раз по статусу) получается часто, и каждый раз обрабатывать одни и те же данные (а они могли не меняться несколько дней) будет затратно. Если смотреть пример, то в таблице Course будут много курсов которые уже закончились и стоят со статусом "Сдан". А такие курсы программе-клиенту если и нужны, то крайне редко. А если постоянно дёргать их и пересчитывать, то получится что постоянно придётся брать ВСЮ таблицу Course и постоянно делать одну и ту же операцию по присвоению статуса, независимо от того, были ли изменения у наследников (Student). Если я правильно понял summary table, то статус переданный в Course на основе статусов из таблицы Student это уже и есть в каком-то смысле summary table. Старыми статусами приходится пренебрегать до момента получения новых, но это ограничение апи, и ничего с этим не поделать. 1. Получили обновления из апи в Student 2. Пересчитали все статусы и передали родителю в Course 3. Все программы счастливы получают курсы типа
Но с таким объёмом на регулярной основе я не работал, поэтому и спрашиваю как лучше поступить. Были большие базы, но я оттуда только получал данные, а не добавлял. С триггером проще это сделать, так как в изменяемой или добавляемой записи обязательно есть Student.CounterId, по которому можно получить и все Student.Status и обновить этот статус в Counter.Status, но нагрузка мне кажется будет большой. А вот без триггера (даже с меткой времени) придётся перебирать всё в цикле Вот мысль про метку времени обновления: Если добавить в Student дополнительное поле TimeStamp и вписывать время последнего изменения, то по этому изменению можно будет пересчитывать ТОЛЬКО те строки, в которых были изменения за прошедший час. Типа получить все Student.CounterId в которых Student.TimeStamp > указанной даты. Затем проверять Student.Statusпо указанным Student.CounterId и передавать уже их в Course.Status Но это всё в цикле, а если в цикле, то наверное это придётся делать на уровне приложения, а не в самой СУБД.
0
|
||||||||||||
|
Модератор
|
||||||||||||||||
| 04.06.2021, 08:37 | ||||||||||||||||
|
В моём понимании, нужна БД для таких сущностей
1
|
||||||||||||||||
|
|
||||||
| 04.06.2021, 08:38 | ||||||
|
BeginnerCoderCS, я как-то давно сваял хранимку для MS SQL Server 2008, которая рассчитывает и записывает статусы поставки по позициям спецификации и статусы поставки заявки полностью в зависимости от того, сколько материала присутствует на складе. Работает вроде шустро, по крайней мере тормозов пока не заметил
Вдруг будет полезно, может как-то переделаете для себя ![]()
1
|
||||||
|
Модератор
|
||
| 04.06.2021, 08:45 | ||
|
BeginnerCoderCS, вы неправильно поняли.
Таблица CourseStatus так же будет считаться однократно при обновлении. Но клиент по запросу получит все (не нулевые) Статусы нужного курса. И сам уже решит что ему нужно для анализа. Добавлено через 2 минуты Тогда да, никакого отключения не нужно. Добавлено через 2 минуты BeginnerCoderCS, по поводу полной таблицы статусов курсов. По сути эта информация всё равно будет считаться и вопрос только в том, запомнить её полностью (5-10-20 строк из трёх int полей на каждый курс), или только одну из этих строк.
1
|
||
|
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
|
|||
| 04.06.2021, 08:46 [ТС] | |||
|
По приоритетам Допустим текущий приоритет: Принят = 0 Отсутствовал = 4 Должник = 2 Не Сдал = 3 Сдал = 1 Затем заказчик скажет, что отключаем передачу статуса Принят = 0, и Должник = 2 в Course, Так как по каким-то причинам, теперь не нужны будут эти статусы. То есть новый приоритет будет Отсутствовал = 4 Не Сдал = 3 Сдал = 1 Или меняем последовательность Не Сдал = 3 Отсутствовал = 4 Должник = 2 Принят = 0 Сдал = 1 Эти изменения могут быть, такак заказчик об этом предупредил. То есть ему не нужно это выводить в интерфейс, это не гибкая настройка, но предупреждение было, что изменения в дальнейшем могут быть, чтобы я не захардкодил этот момент. С доп таблицей приоритетов мне нравится идея, но что-то я не с той стороны захожу наверное, так как не могу реализовать нормально.
0
|
|||
| 04.06.2021, 08:46 | |
|
Как правильно отлавливать Constraint ForeignKey в DAO? Как изменить отображение текста ForeignKey в моделе Как шифровать файлы при передаче на сервер и дешефровать при передаче с сервера на клиент Как сделать каскадный вызов элементов ForeignKey в одной view в Django? Как посмотреть наследников класса Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла:
Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
|
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет
Новости компьютерного мира и их обсуждение (4)
Салют, шампанское, овации!
:drink:
|
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр.
Дословно, отклонённая. . .
|
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы
Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
|
|
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
|
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2.
Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
|
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
|
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
|