C>Представь, что у нас есть две таблицы Person (id, date_created) и PersonalDetails(id, parent_id, name, last_name). Мы делаем запрос "SELECT pers.id, det.name, det.last_name FROM Person pers, PersonalDetails det where pers.id=det.parent_id" и кладём его результаты в кэш.
C>Теперь на сервере у нас поменялся PersonalDetails (Мария Иванова вышла замуж и стала Марией Петровой, а инженер Василий поменял пол и стал Василией). Но обновить кэш корректно мы не можем! У нас в нём нет связи между этими таблицами.
Почему не можем? Нам же всё известно. В зависимости от степени нашего усердия, мы получим
а) нулевое кэширование: все результаты считаются устаревшими сразу по возврату
б) простое пессимистичное кэширование: для каждого исходного набора данных (person, personDetails, и так далее) хранится таймстамп модификации. При его изменении результат считается устаревшим целиком
в) простое точное кэширование: для каждой строки исходного набора данных хранится таймстамп модификации. При запросе вычисляется most recent change time; если он новее результата — весь результат считается устаревшим
г) детальное точное кэширование: клиент хранит MRCT для каждой строки результата; при обновлениях обновляются только те строки, которые были фактически изменены.
ORM-ам до этого как до китая пешком.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Lloyd, Вы писали: L>Мы сами подобное используем, я имею в виду создание отдельных PE для отдельных страниц. И меня совершенно не радует созерцать кучу одноразовых классов. Так что так уж однозначно называть этот способ правильным я бы не стал.
А что именно в одноразовых классах тебя смущает? Меня вот гораздо больше смущает насильственное использование плохо приспособленных классов.
Просто мы очень привыкли к тому, что класс — это дорогостоящая штука, которую надо обязательно руками описать заранее, и очень многословно. И потом нужно его поддерживать, внося изменения.
Однако внедрение более эффективных методик порождения типов позволяет сделать эти одноразовые классы достаточно дешевыми. Те же анонимные типы использовать почти так же приятно, как и именованные, при этом нет нужды описывать их заранее в отдельном месте.
L>Но это не является параметром выборки
Не играй словами. Набор полей является существенным свойством оператора выборки, которое значительно влияет на производительность запроса.
L>Не один, а пачка: если у кастомера в адресе нужно выбрать город, то здравствуй новая PE с двумя полями ID и Name.
Ну и что? Какие проблемы? Я не очень понимаю, что ты имеешь в виду под PE. Будет просто свойство ViewModel, в котором лежит коллекция пар ID и Name. Всё очень здорово и удобно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
C>>Теперь на сервере у нас поменялся PersonalDetails (Мария Иванова вышла замуж и стала Марией Петровой, а инженер Василий поменял пол и стал Василией). Но обновить кэш корректно мы не можем! У нас в нём нет связи между этими таблицами. S>Почему не можем? Нам же всё известно. В зависимости от степени нашего усердия, мы получим
Не можем. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails.
S>а) нулевое кэширование: все результаты считаются устаревшими сразу по возврату
Ага.
S>б) простое пессимистичное кэширование: для каждого исходного набора данных (person, personDetails, и так далее) хранится таймстамп модификации. При его изменении результат считается устаревшим целиком
Не пойдёт. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails.
S>в) простое точное кэширование: для каждой строки исходного набора данных хранится таймстамп модификации. При запросе вычисляется most recent change time; если он новее результата — весь результат считается устаревшим
Не пойдёт. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails.
S>г) детальное точное кэширование: клиент хранит MRCT для каждой строки результата; при обновлениях обновляются только те строки, которые были
фактически изменены.
Не пойдёт. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails.
S>ORM-ам до этого как до китая пешком.
У меня это _уже_ работает с ORM. С сервера приходят дельты вида (ClassName, ID) -> changed_property, которые накладываются на локальный кэш. С полной поддержкой обновления коллекций.
Здравствуйте, VladD2, Вы писали:
VD>Это догмы введенные дизайнирами дотнета. Структурная идентичность — это примитивная возможность, реализовать которую в дотнете было бы элементарно. Нужно только желание. Ввели бы некий атрибут говорящий, что для типа помеченного им работает структурная идентичность.
А, вот наверное и есть то решение, которое всему поможет.
Но вот насчёт примитивности я не уверен.
Как только ты сделал два типа совместимыми, начинаются разнообразные смешные сценарии использования — например, употребить тип в параметре делегата.
Или отнаследоваться от такого "типа со структурной идентичностью". В итоге получается большое количество corner cases, которые должны работать осмысленным образом. Это существенно увеличивает объем QA.
Ну вот к примеру — будут ли два массива таких типов совместимы по присваиванию, как это работает для string[]->object[]?
VD>Это как раз очено даже правильно, коль в язык регистро-зависимый. VD>Ничего тут интуитивно не понятно. В прочем правило игнорирования регистра тоже можно было бы ввести для совместимости с разными VB. Регистр тут ни при чём. {string Name, int Age} должен быть совместимым с любым {string, int}. См. SQL — там это используется сплошь и рядом.
VD>Не у кортежей просто нет имен полей. Можно сделать совместимость между записью и кортежем. Тогда при желании можно будет скопировать разные записи друг в друга через кортеж. Но прилеплять кортежи к записям не стоит. Это разные, хотя и родственные типы.
В чем отличие? Зачем иметь два типа, выполняющих сходную функцию? Имхо, вполне достаточно одного, но полноценного.
VD>Скажем так. Реализовать копирование между записями и кортежами.
С копированием есть еще несколько тонких вопросов — это же операция, нарушающая идентичность. Хотя, если считать, что ее у структурных типов быть вовсе не должно... Тем не менее, копирование не спасает для приведения друг к другу IEnumerable<T> и T[]. А без него смысла во взаимозаменяемости особого нету.
VD>А вот это плохое решение. Лучше ввести атрибут структурной совместимости и пометить ими анонимные типы.
Почему плохое?
VD>А если бы была структурная совместимость, то проблем бы не возникло. Так что вердикт ясен как божий день. Еще один косяк в системе типов донета который Майкрософт упорно не хочет исправлять.
Ну, не факт, что не хочет, и не факт, что упорно. Я вот, с учетом малого опыта работы с ФП-языками, пока что плохо представляю даже постановку задачи.
VD>Потому что ты исходишь из неверных предпосылок. Нужно не заплаты придумывать, а ошибки исправлять.
Ну, если есть детальное представление о том, как именно нужно исправить ошибку — то велкам.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
A>>Влад, мы не реплицируем БД. в данном случае репликация — это костыль для твоей системы неспособной к локальному кешированию. S>Это как раз ОRM-системы неспособны к локальному кэшированию. Там кэш может быть исключительно глобальный, иначе ты мгновенно напорешься на рассогласование. S>А в linq-подходе, о котором говорит Влад, запросто можно (если нужно) кэшировать конкретный результат конкретного запроса. S>На практике, к примеру, работа с почтой через OWA жрет в разы меньше трафика, чем честная синхронизация Outlook.
А ты ещё латентность сравни. С локальной базе в Outlook'е операции проходят _мгновенно_.
Здравствуйте, Cyberax, Вы писали: C>Не можем. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails.
Гм. Если обновления кэша приходят в таком виде — это чистой воды ошибка архитектора. Зачем он спроектировал обновлялку таким неприменимым образом? Подсказка: кэш в HTTP работает безо всяких PK.
S>>ORM-ам до этого как до китая пешком. C>У меня это _уже_ работает с ORM. С сервера приходят дельты вида (ClassName, ID) -> changed_property, которые накладываются на локальный кэш. С полной поддержкой обновления коллекций.
У нас это работало в 1998 году. Поэтому я знаю, о чем говорю — эта технология сосёт.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали: S>>На практике, к примеру, работа с почтой через OWA жрет в разы меньше трафика, чем честная синхронизация Outlook. C>А ты ещё латентность сравни. С локальной базе в Outlook'е операции проходят _мгновенно_.
Ну, с локальной базой в 5.4 GB особенной мгновенности я не замечаю. Что будет при 10GB?
Да, когда я сижу из Кемеровской области по GPRS, OWA работает неторопливо.
А вот по локальному каналу всё летает достаточно шустро. И это я еще не смотрел на OWA от Exchange 14, а они вроде как ее подкрутили.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Lloyd, Вы писали:
L>>>Раз ты удалил отквоченый текст, то напомню, о чем идет речь: L>>>
L>>>Например, некоторые параметры не хранятся один-в-один в полях таблицы, а сериализуются в xml-ную колонку. Наличие DAL-а позволяет этот механизм хранения скрыть от бизнеса, что, имхо, очень удобно и позволяет очень просто дополнять поля сущности.
VD>>Ну, и скрывай эти детали. Что тебе мешает, то?
L>Отсутствие DAL-а, вестимо. Entity-то отличается от схемы данных.
От повторения одного и того же оно правдой не становится. В EF маппинг, даже нетривиальный, делается без DAL.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Cyberax, Вы писали: C>>Не можем. Обновления будут приходить в виде карты PK -> data, а в нашем запросе мы потеряли PK для PersonDetails. S>Гм. Если обновления кэша приходят в таком виде — это чистой воды ошибка архитектора. Зачем он спроектировал обновлялку таким неприменимым образом? Подсказка: кэш в HTTP работает безо всяких PK.
Не, ну это смешно. Тебе никто никогда не говорил, что:
1) Бывают "толстые" клиенты.
2) Запрос на сервер — это заметная латентность.
C>>У меня это _уже_ работает с ORM. С сервера приходят дельты вида (ClassName, ID) -> changed_property, которые накладываются на локальный кэш. С полной поддержкой обновления коллекций. S>У нас это работало в 1998 году. Поэтому я знаю, о чем говорю — эта технология сосёт.
А точо работало?
Здравствуйте, Sinclair, Вы писали:
C>>А ты ещё латентность сравни. С локальной базе в Outlook'е операции проходят _мгновенно_. S>Ну, с локальной базой в 5.4 GB особенной мгновенности я не замечаю. Что будет при 10GB?
А это уже проблемы проектировщиков приложения, не умеющих строить индексы.
S>Да, когда я сижу из Кемеровской области по GPRS, OWA работает неторопливо.
Вот, а у меня в аналогичной ситуации клиент работает без всяких задержек.
S>А вот по локальному каналу всё летает достаточно шустро. И это я еще не смотрел на OWA от Exchange 14, а они вроде как ее подкрутили.
По локальному каналу вообще плевать как делать, можно хоть скриншоты гонять в realtime.
Здравствуйте, Cyberax, Вы писали: C>Не, ну это смешно. Тебе никто никогда не говорил, что: C>1) Бывают "толстые" клиенты.
И как это противоречит модели кэширования, не построенной на PK? Ты, собственно, пытаешся изобрести на коленке то, что в мире СУБД называется Replication based on log shipping.
А я пытаюсь объяснить то, что кэш вовсе не обязан воспроизводить структуру серверной БД, и log shipping — не единственное решение для обновлений кэша.
Я понимаю, это трудно понять, рассматривая кэш только как локальную реплику. C>2) Запрос на сервер — это заметная латентность.
А это тут причём? Если есть обновления — их нужно как-то передать. Кто-то предполагает, что log shipping превысит скорость света и станет работать без латентности?
Нет, он работает по ровно тому же каналу. Вот только надо постараться, чтобы он не реплицировал лишних данных — я уже приводил пример про потребление трафика аутлуком.
C>А точо работало?
Еще как. Я тогда уверовал в ORM как в манну небесную.
Вот только мы никак не могли нужную производительность получить — работало всё только на синтетических примерах. Ну, то есть тогда сто мегабит были дорогой редкостью.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
C>>1) Бывают "толстые" клиенты. S>И как это противоречит модели кэширования, не построенной на PK? Ты, собственно, пытаешся изобрести на коленке то, что в мире СУБД называется Replication based on log shipping.
Ага.
S>А я пытаюсь объяснить то, что кэш вовсе не обязан воспроизводить структуру серверной БД, и log shipping — не единственное решение для обновлений кэша. S>Я понимаю, это трудно понять, рассматривая кэш только как локальную реплику.
Я понимаю, что возможны другие методы, но они все обладают существенными недостатками. Основной и самый фатальный из них — невозможность делать локальные запросы.
C>>2) Запрос на сервер — это заметная латентность. S>А это тут причём? Если есть обновления — их нужно как-то передать. Кто-то предполагает, что log shipping превысит скорость света и станет работать без латентности?
Нет. Я для большинства целей обхожусь локальными запросами, которые работают с репликой БД. Соответственно, нулевая латентность.
S>Нет, он работает по ровно тому же каналу. Вот только надо постараться, чтобы он не реплицировал лишних данных — я уже приводил пример про потребление трафика аутлуком.
Outlook реплицирует всю базу целиком. У меня реплицируется только working set.
C>>А точо работало? S>Еще как. Я тогда уверовал в ORM как в манну небесную. S>Вот только мы никак не могли нужную производительность получить — работало всё только на синтетических примерах. Ну, то есть тогда сто мегабит были дорогой редкостью.
Ха! У меня приложение работает прекрасно даже на модеме. Благодаря тому, что на сервер обращения идут очень редко, а объём меняющихся данных весьма мал.
Собственно, у меня приложение специально заточено для работы на неустойчивых каналах — пришлось даже для этого свой протокол RPC делать. Я об этом как-то писал.
Здравствуйте, Sinclair, Вы писали:
S>(from o in orders where o.OrderDate < xxx select o).Update(o => o.SetDelayed(true)); S>В предположении, что SetDelayed имеет семантику
А как для двух полей?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали: S>>Да, когда я сижу из Кемеровской области по GPRS, OWA работает неторопливо. C>Вот, а у меня в аналогичной ситуации клиент работает без всяких задержек.
Тут вопрос тонкий. Ок, допустим, аутлук работает "без задержек" на мелких UI операциях. А вот ожидание окончания синхронизации мы в эти задержки будем включать?
Ну и всё-таки не до конца понятно, "в такой" ли ситуации ты проверял. C>По локальному каналу вообще плевать как делать, можно хоть скриншоты гонять в realtime.
Угу. Вот только в развитом мире широкополосного интернета значительно больше, чем узкополосного. Вон народ через сеть видео в 720p смотрит — и не жужжит. Я тут наш собственный продукт пощупал через узкий канал — умереть ведь можно. А наши клиенты даже не замечают того, что мы делаем всякие full-page refresh или того, что у нас иконки не кэшируются. Вот такая вот альтернативная реальность. А какой-ндь Page Flakes, который спроектирован грамотно, вообще летает на практически любых каналах. Редкий толстый клиент сможет его порвать.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
C>>Вот, а у меня в аналогичной ситуации клиент работает без всяких задержек. S>Тут вопрос тонкий. Ок, допустим, аутлук работает "без задержек" на мелких UI операциях. А вот ожидание окончания синхронизации мы в эти задержки будем включать?
А это смотря как её сделать...
S>Ну и всё-таки не до конца понятно, "в такой" ли ситуации ты проверял.
То есть?
C>>По локальному каналу вообще плевать как делать, можно хоть скриншоты гонять в realtime. S>Угу. Вот только в развитом мире широкополосного интернета значительно больше, чем узкополосного.
Ага. В развитом мире ещё полно клиентов с криворукими админами, умеющими только Windows XP устанавливать, у которых каналы забиты наглухо вирусами.
S>Вон народ через сеть видео в 720p смотрит — и не жужжит. Я тут наш собственный продукт пощупал через узкий канал — умереть ведь можно. А наши клиенты даже не замечают того, что мы делаем всякие full-page refresh или того, что у нас иконки не кэшируются. Вот такая вот альтернативная реальность. А какой-ндь Page Flakes, который спроектирован грамотно, вообще летает на практически любых каналах. Редкий толстый клиент сможет его порвать.
Вот буквально на прошлой неделе у нас появился новый клиент, они отказались от продукта конкурента из-за того, что у нас клиент намного более приятный в использовании. Конкурент делает чистое web-приложение.
(from o in orders where o.OrderDate < xxx select o).
Update(o => o.SetDelayed(true)).
Update(o => SetDiscount(o.discount + Consts.DelayDiscountRate)); // кстати чисто в теории такие методы вполне можно мапить на хранимые процедуры - вообще ляпота будет.
Проще парсить expression tree. Да и в концепцию IQueryable лучше вписывается.
Здравствуйте, Sinclair, Вы писали:
S>Редкий толстый клиент сможет его порвать.
Кстати, могу как-нибудь мой клиент тебе показать Посмотрим, сможешь ли ты его порвать.
Здравствуйте, Cyberax, Вы писали:
S>>Тут вопрос тонкий. Ок, допустим, аутлук работает "без задержек" на мелких UI операциях. А вот ожидание окончания синхронизации мы в эти задержки будем включать? C>А это смотря как её сделать...
Подробнее. Вот Аутлук, к примеру, синхронизуется в обратном порядке и избегает глобальной блокировки (в отличие от RSDN@Home). Тем не менее, ситуация, когда мне нужно подождать 5-10 минут для того, чтобы принять приглашение на митинг, для узкого канала вполне типична. На том же канале то же действие через OWA займет 40-80 секунд.
Есть какие-то мегарешения, помогающие толстому репликатору?
C>То есть?
Какой именно был канал.
С чем именно сравнивалось.
C>Ага. В развитом мире ещё полно клиентов с криворукими админами, умеющими только Windows XP устанавливать, у которых каналы забиты наглухо вирусами.
Я говорю о наблюдаемой нами действительности, а не о подростковых эротических мечтах о превосходстве безвирусного линукса.
C>Вот буквально на прошлой неделе у нас появился новый клиент, они отказались от продукта конкурента из-за того, что у нас клиент намного более приятный в использовании. Конкурент делает чистое web-приложение.
Конкурент может делать всё, что угодно. Пока что в мире очень немного людей, умеющих готовить хорошие веб-приложения. Умеющих готовить хороших толстых клиентов, впрочем, тоже немного. То, что ты сумел решить задачу толстым клиентом, а конкурент не смог вебприложением, ничего не говорит о свойствах архитектуры в целом. Это говорит только о квалификации тебя и конкурента.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Подробнее. Вот Аутлук, к примеру, синхронизуется в обратном порядке и избегает глобальной блокировки (в отличие от RSDN@Home). Тем не менее, ситуация, когда мне нужно подождать 5-10 минут для того, чтобы принять приглашение на митинг, для узкого канала вполне типична. На том же канале то же действие через OWA займет 40-80 секунд. S>Есть какие-то мегарешения, помогающие толстому репликатору?
Могу рассказать как я бы эту проблему решил.
C>>То есть? S>Какой именно был канал. S>С чем именно сравнивалось.
Я беру обычный модем (в моём ноуте) и проверяю как на нём всё работает. Разницы между модемом и толстым каналом практически не было. На GPRS и 3G-модеме я тоже проверял.
Толстый канал, кстати, тоже у меня не особо замечательный. Латентность порядка 300 миллисекунд (сервер в штате Washington) и пропускная способность около 20-30 килобайт в секунду (что-то с роутингом у провайдеров не то).
C>>Ага. В развитом мире ещё полно клиентов с криворукими админами, умеющими только Windows XP устанавливать, у которых каналы забиты наглухо вирусами. S>Я говорю о наблюдаемой нами действительности, а не о подростковых эротических мечтах о превосходстве безвирусного линукса.
Я и говорю об окружающей действительности — у кучи наших клиентов очень отстойные каналы связи. Это объективная реальность такая.
S>Конкурент может делать всё, что угодно. Пока что в мире очень немного людей, умеющих готовить хорошие веб-приложения. Умеющих готовить хороших толстых клиентов, впрочем, тоже немного. То, что ты сумел решить задачу толстым клиентом, а конкурент не смог вебприложением, ничего не говорит о свойствах архитектуры в целом. Это говорит только о квалификации тебя и конкурента.
Самое прикольное, что наш самый опасный конкурент сейчас делает не web-приложение, а консольного клиента к COBOL'ному серверу (я уже стенку головой пробил, пока писал мигратор с него).