Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>Не понял, что именно сделать джоином?
VD>Выборку данных.
Я же и говорю что явный джоин гораздо лучше LL.
А проблема SELECT N+1 в основном не так явно выглядит.
Обычно что-то в этом роде:
public class Order
{
//LLCollection не IQueryable, поэтому при ленивой загрузке вытягиваются полные объектыpublic LLCollection<OrderLine> OrderLines { get; }
public decimal Total
{
get
{
return OrderLines.Sum(l => l.Price * l.Quantity);
}
}
}
//в другом методе, в другой сборке, написанной другим человеком
...
var orders = dal.GetSomeOrders(...)
var sum = orders.Sum(o => o.Total);
...
Ну вот как-то так.
Re[40]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Ziaw, Вы писали:
Z>>Я рассматриваю построение модели не как способ сокрытия реляционности, а как способ создать удобный ДСЛ для запросов.
VD>Удобнее чем LINQ все равно создать не получится. Так что ты прост делаешь бессмысленную работу.
Так LINQ прикручивают к гибернейту и если год назад я утверждал, что та реализация тупиковая, то сейчас вижу нормальное решение.
А год назад не было альтернатив с поддержкой линка для нормального построения модели под требуемые нам СУБД.
Впрочем и сейчас тулкит в продакшен пускать рисковано.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[38]: Фреймфорк для разработки Веб и десктоп-приложений на
G>public class Order
G>{
G> //LLCollection не IQueryable, поэтому при ленивой загрузке вытягиваются полные объекты
G> public LLCollection<OrderLine> OrderLines { get; }
G> public decimal Total
G> {
G> get
G> {
G> return OrderLines.Sum(l => l.Price * l.Quantity);
G> }
G> }
G>}
G>//в другом методе, в другой сборке, написанной другим человеком
G>...
G>var orders = dal.GetSomeOrders(...)
G>var sum = orders.Sum(o => o.Total);
G>...
G>
G>Ну вот как-то так.
Если GetSomeOrders возвращает запрос, то они просто сокомбинируются и в результате получится единый запрос который будет оптимизирован SQL-сервером.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[41]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Ziaw, Вы писали:
VD>>Удобнее чем LINQ все равно создать не получится. Так что ты прост делаешь бессмысленную работу.
Z>Так LINQ прикручивают к гибернейту и если год назад я утверждал, что та реализация тупиковая, то сейчас вижу нормальное решение. Z>А год назад не было альтернатив с поддержкой линка для нормального построения модели под требуемые нам СУБД. Z>Впрочем и сейчас тулкит в продакшен пускать рисковано.
Допишет до коныа, отладит и будет все ОК. Кибернэйт пока что тоже полноценно LINQ не поддерживает.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[39]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>
G>>public class Order
G>>{
G>> //LLCollection не IQueryable, поэтому при ленивой загрузке вытягиваются полные объекты
G>> public LLCollection<OrderLine> OrderLines { get; }
G>> public decimal Total
G>> {
G>> get
G>> {
G>> return OrderLines.Sum(l => l.Price * l.Quantity);
G>> }
G>> }
G>>}
G>>//в другом методе, в другой сборке, написанной другим человеком
G>>...
G>>var orders = dal.GetSomeOrders(...)
G>>var sum = orders.Sum(o => o.Total);
G>>...
G>>
G>>Ну вот как-то так.
VD>Если GetSomeOrders возвращает запрос, то они просто сокомбинируются и в результате получится единый запрос который будет оптимизирован SQL-сервером.
Нет, потому что вычисление тотала не будет распознано.
Кроме того начитавшись фаулера люди пишут DAL, возвращающий коллекции объектов, а не IQueryable.
Я аналогичный код видел в одном проекте.
Re[40]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
G>Нет, потому что вычисление тотала не будет распознано.
Это почему же?
Да и на крайняк должна быть ошибка типизации.
G>Кроме того начитавшись фаулера люди пишут DAL, возвращающий коллекции объектов, а не IQueryable.
Это, да.
Откровенно говоря возможность мешать запросы к коллекциям с запросами к удаленным данным может привести к куче проблем. Казалось бы красивое решение, но опасное.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[41]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>Нет, потому что вычисление тотала не будет распознано.
VD>Это почему же?
Ну потому что тотал возвращает decimal. Для получения внутреностей придется IL разбирать.
Re[51]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>Можно. Но в UDF это делается уродливо. Проходили уже, первая версия ровно так и работала — делался row-level security в Оракульной БД. C>>Оно в итоге под своим весом всё упало. G>Я же и говорю — кешировать надо.
А ты думаешь это так просто?
C>>На клиенте данные не фильтруются (я идиот, что ли?) G>А где фильтруются? Ты же говорил что обработка не ложится на SQL... G>Или я что-то не так понял.
На сервере перед выдачей клиенту, специальным кодом. На практике, отфильтровывается не так много объектов, так что даже особо не оптимизировали изначальное получение данных.
C>>О, так у нас уже всё через определённый слой идёт? И никаких массовых update'ов нет? G>Если есть массовые апдейты, то вмето конкретного ключа можно получить предикат на выборку нужных записей. G>Но я сейчас EF использую, у него с массовыми операциям совсем плохо.
Предикат будет работать и на клиенте?
C>>Так поздравляю, ты почти написал H/ORM! Ещё чуть-чуть, и оно будет готово. G> Ну если пара сотен строк кода для реализации такого функционала — H/ORM, то да, я написал H/ORM G>как раз подобным образом делал отправку сообщений аудита.
Тебе ещё из большого функционала нужна только реализация коллекций. И всё, получается классика ORM.
G>>>И зачем тогда их все тянуть на клиента? C>>А то, что ты можешь часть фильтрации делать на клиенте. Скажем, поиск по словам в таблице. G>По каким словам, в какой таблице?
Есть у тебя таблица типа с колонками "Имя", "Адрес", "Город", "Телефон". И рядом с ней поле ввода, и если туда ввести "Jo D 123", оно найдёт запись "John Doe, Some street, Some City, (123)-13241246". Мгновенно, точнее будет искать прямо пока ты вводишь.
Чрезвычайно удобная фича.
G>>>Ну с ACL уже разобрались — вполне ложится на SQL. C>>Не ложится. G>Ну покажи где?
Построение иерарихй.
G>Я так понимаю что стоит создать в базе списски эффективных ACL и эффективных ролей для пользователя (например на триггерах). Тогда можно фильтровать записи на севрере прямо в запросе, без вытягивания acl из базы.
Я же говорю — получается жуть. Меняется ACL у родителя — и нужно пересчитывать кэши всех детей. Не пропуская ничего, вдобавок.
Кроме того, сейчас у меня код — database independent. И работает под PostgreSQL, Oracle и (прости Боже!) MySQL. Как такое же на триггерах сделать?
G>>>Можем еще что-нибудь разобрать, не сомневаюсь что тоже окажется нормально ложащимся на SQL. C>>Спорим? G>ну давай.
Товар принадлежит одной или нескольким группам (обычный many-to-many). Нужно найти все наборы групп, и вывести для них товары.
Т.е. у нас есть "Brick" в группах "Materials" и "Tools for Killers" и "Knife" в группе "Tools for Killers". Нужно вывести:
"Materials, Tools for Killers" -> "Brick"
"Tools for Killers" -> "Brick"
"Tools for Killers" -> "Knife"
Причём название группы должно быть хитро отсортировано (скажем, по весу). Последняя попытка дала килобайтный SQL-запрос. Хотя императивно оно пишется в десяток строк кода.
А ещё есть запросы со всякими running sums и delta'ами между строками...
Так что не надо считать реляционную модель концом всего. Это неплохой подход, но далеко не единственный и далеко не всегда лучший.
G>>>Причем для последних работать эффективнее будет. C>>Проблема с их _обновлением_. G>Никаких проблем. last modified отлично работает.
Ты ещё скажи "SQL отлично работает". Каким образом ты будешь обновлять связные кэши?
G>>>Кроме того решение на HTTP будет неограниченно масштабироваться. C>>А кто будет фильтровать результаты для каждого пользователя? Видимо, reverse proxy? G>В этом случае reverse proxy не поможет. Кеш на клиенте все равно работать будет.
А как насчёт инкрементальности? Будем все 500 килобайт результатов каждого запроса перегружать пару раз в пару секунд?
В общем, ты даже и близко не понимаешь сложности задачи.
Sapienti sat!
Re[52]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, gandjustas, Вы писали:
C>>>Можно. Но в UDF это делается уродливо. Проходили уже, первая версия ровно так и работала — делался row-level security в Оракульной БД. C>>>Оно в итоге под своим весом всё упало. G>>Я же и говорю — кешировать надо. C>А ты думаешь это так просто?
Все равно придется писать код вычисления "эффективных ACL" и прав пользователя, причем именно в БД, чтобы не тащить кучу данных из базы.
А вызывать этот алгоритм в триггере на изменения и складывать результаты в таблицу гораздо проще.
C>>>На клиенте данные не фильтруются (я идиот, что ли?) G>>А где фильтруются? Ты же говорил что обработка не ложится на SQL... G>>Или я что-то не так понял. C>На сервере перед выдачей клиенту, специальным кодом. На практике, отфильтровывается не так много объектов, так что даже особо не оптимизировали изначальное получение данных.
C>>>О, так у нас уже всё через определённый слой идёт? И никаких массовых update'ов нет? G>>Если есть массовые апдейты, то вмето конкретного ключа можно получить предикат на выборку нужных записей. G>>Но я сейчас EF использую, у него с массовыми операциям совсем плохо. C>Предикат будет работать и на клиенте?
ну если надо, то да.
G>>>>И зачем тогда их все тянуть на клиента? C>>>А то, что ты можешь часть фильтрации делать на клиенте. Скажем, поиск по словам в таблице. G>>По каким словам, в какой таблице? C>Есть у тебя таблица типа с колонками "Имя", "Адрес", "Город", "Телефон". И рядом с ней поле ввода, и если туда ввести "Jo D 123", оно найдёт запись "John Doe, Some street, Some City, (123)-13241246". Мгновенно, точнее будет искать прямо пока ты вводишь.
С задержкой, равной латентности сети.
G>>>>Ну с ACL уже разобрались — вполне ложится на SQL. C>>>Не ложится. G>>Ну покажи где? C>Построение иерарихй.
CTE уже отменили?
G>>Я так понимаю что стоит создать в базе списски эффективных ACL и эффективных ролей для пользователя (например на триггерах). Тогда можно фильтровать записи на севрере прямо в запросе, без вытягивания acl из базы. C>Я же говорю — получается жуть. Меняется ACL у родителя — и нужно пересчитывать кэши всех детей. Не пропуская ничего, вдобавок.
Да, именно так.
И часто меняется ACL сильно родительской записи? И какова глубина иерархий?
C>Кроме того, сейчас у меня код — database independent. И работает под PostgreSQL, Oracle и (прости Боже!) MySQL. Как такое же на триггерах сделать?
Писать триггеры под разные базы, тем более их довольно небольшое количество.
G>>>>Можем еще что-нибудь разобрать, не сомневаюсь что тоже окажется нормально ложащимся на SQL. C>>>Спорим? G>>ну давай. C>Товар принадлежит одной или нескольким группам (обычный many-to-many). Нужно найти все наборы групп, и вывести для них товары.
C>Т.е. у нас есть "Brick" в группах "Materials" и "Tools for Killers" и "Knife" в группе "Tools for Killers". Нужно вывести: C>"Materials, Tools for Killers" -> "Brick" C>"Tools for Killers" -> "Brick" C>"Tools for Killers" -> "Knife"
C>Причём название группы должно быть хитро отсортировано (скажем, по весу). Последняя попытка дала килобайтный SQL-запрос. Хотя императивно оно пишется в десяток строк кода.
EF:
var q = from p in db.Products
select {Product = p, Groups = p.Groups.OrderBy(g => g.Wheight)};
Вот как-то так.
C>А ещё есть запросы со всякими running sums и delta'ами между строками...
Ну это тот самый случай когда императивный код в SQL рулит.
Хотя я бы в MS SQL сложные аггрегаты делал бы с помощью CLR расширений.
C>Так что не надо считать реляционную модель концом всего. Это неплохой подход, но далеко не единственный и далеко не всегда лучший.
Как раз реляционная работа с данными — самый лучший вариант работы с данными.
Вот только некоторые простые для императивной обработки вещи в SQL потребуют correlated subquery и офигенную сложность выполнения.
G>>>>Причем для последних работать эффективнее будет. C>>>Проблема с их _обновлением_. G>>Никаких проблем. last modified отлично работает. C>Ты ещё скажи "SQL отлично работает". Каким образом ты будешь обновлять связные кэши?
изменился last modified — кеш обновился.
Ты знаешь как кеширование в HTTP работает?
G>>>>Кроме того решение на HTTP будет неограниченно масштабироваться. C>>>А кто будет фильтровать результаты для каждого пользователя? Видимо, reverse proxy? G>>В этом случае reverse proxy не поможет. Кеш на клиенте все равно работать будет. C>А как насчёт инкрементальности? Будем все 500 килобайт результатов каждого запроса перегружать пару раз в пару секунд?
А зачем их перезагружать? Они реально пару раз в секунду меняются?
Повысить гранулярность можно, тогда придется гораздо меньше перезагружать.
C>В общем, ты даже и близко не понимаешь сложности задачи.
Да сложность задачи я отлично понимаю.
Я вот сложности твоего решения не понимаю.
Re[53]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>А ты думаешь это так просто? G>Все равно придется писать код вычисления "эффективных ACL" и прав пользователя, причем именно в БД, чтобы не тащить кучу данных из базы.
А данные всё равно будут подниматься перед выдачей их клиенту. Так что однофигственно.
G>А вызывать этот алгоритм в триггере на изменения и складывать результаты в таблицу гораздо проще.
Ничуть. Особенно приятно, что количество таблиц примерно утраивается, ну и для ACLей ещё нужно имитировать "наследование", которое в БД нормальными средствами не делается.
C>>Предикат будет работать и на клиенте? G>ну если надо, то да.
Надо.
C>>Есть у тебя таблица типа с колонками "Имя", "Адрес", "Город", "Телефон". И рядом с ней поле ввода, и если туда ввести "Jo D 123", оно найдёт запись "John Doe, Some street, Some City, (123)-13241246". Мгновенно, точнее будет искать прямо пока ты вводишь. G>С задержкой, равной латентности сети.
С задержкой, минимально ограниченной латентностью сети. К примеру, если пользователей порядка 2000 и у каждого из них по 3 адреса — запрос уже будет выполняться ощутимое время. А ещё учитываем время на передачу результатов. На практике оно весьма тормозно получается.
А ещё учитываем возможность использования wildcard'ов, которые замечательно убивают даже полнотекстовые индексы (которые весьма недёшевы, кстати).
В общем, пока ты будешь оптимизировать базу данных — я напишу за минуту простой линейный перебор в самом нереляционном стиле, и не буду мучаться. Он работает на клиенте доли миллисекунды без всяких оптимизаций.
C>>Построение иерарихй. G>CTE уже отменили?
Ага. На MySQL'е, к примеру. Да и вообще они какие-то нереляционные и делают SQL полным по Тьюрингу.
C>>Я же говорю — получается жуть. Меняется ACL у родителя — и нужно пересчитывать кэши всех детей. Не пропуская ничего, вдобавок. G>Да, именно так. G>И часто меняется ACL сильно родительской записи? И какова глубина иерархий?
5-10 элементов. В паре вырожденных случаев около 50.
В общем, очень и очень хрупкое решение.
C>>Кроме того, сейчас у меня код — database independent. И работает под PostgreSQL, Oracle и (прости Боже!) MySQL. Как такое же на триггерах сделать? G>Писать триггеры под разные базы, тем более их довольно небольшое количество.
Во-во. И ACLи тоже. И запросы. И можно ли всё это сделать на MySQL с его странным языком триггеров и SP? А как быть с транзакциями —
Спрашивается: ну и где наглядность L/ORM остаётся-то? Как обычно — только в теории?
C>>Причём название группы должно быть хитро отсортировано (скажем, по весу). Последняя попытка дала килобайтный SQL-запрос. Хотя императивно оно пишется в десяток строк кода. G>EF: G>
G>var q = from p in db.Products
G> select {Product = p, Groups = p.Groups.OrderBy(g => g.Wheight)};
G>
G>Вот как-то так.
Не-не. Это и я могу. Ты мне сделай так, чтоб оно список товаров выводило в том виде, в котором я его написал.
Оно реляционными методами эффективно не решается.
C>>А ещё есть запросы со всякими running sums и delta'ами между строками... G>Ну это тот самый случай когда императивный код в SQL рулит. G>Хотя я бы в MS SQL сложные аггрегаты делал бы с помощью CLR расширений.
Не знаю, может мне везёт, но у меня почему-то большинство таких отчётов.
C>>Так что не надо считать реляционную модель концом всего. Это неплохой подход, но далеко не единственный и далеко не всегда лучший. G>Как раз реляционная работа с данными — самый лучший вариант работы с данными.
Скажи это Гуглу, создателям Couch DB и языка K.
G>Вот только некоторые простые для императивной обработки вещи в SQL потребуют correlated subquery и офигенную сложность выполнения.
Необязательно. Я могу взять нужные данные и руками по ним запустить обработку. На нормальном Turing-complete языке.
C>>Ты ещё скажи "SQL отлично работает". Каким образом ты будешь обновлять связные кэши? G>изменился last modified — кеш обновился. G>Ты знаешь как кеширование в HTTP работает?
"last modified" _на_ _что_?
C>>А как насчёт инкрементальности? Будем все 500 килобайт результатов каждого запроса перегружать пару раз в пару секунд? G>А зачем их перезагружать? Они реально пару раз в секунду меняются? G>Повысить гранулярность можно, тогда придется гораздо меньше перезагружать.
???
Повышаем гранулярность — и перегружаем всю "гранулу" при её изменении. Только объём увеличится.
C>>В общем, ты даже и близко не понимаешь сложности задачи. G>Да сложность задачи я отлично понимаю. G>Я вот сложности твоего решения не понимаю.
А нету сложности. Вся сложность в 50 килобайтах кода перехватчиков событий. И после этого оно всё автоматически.
Тебе зато придётся для каждого вида продумывать кэши, вычислять зависимости (руками!), и молиться чтоб оно работало.
Sapienti sat!
Re[5]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, SHEMA, Вы писали:
SHE>Мы говорим про разработку интерфейса. То что в большинстве проектов ето занимает не самый большой процент времени — не обсуждается.
Повторюсь: менять дизайн — это копейки. Если только вы не юзабелист/дизайнер интерфейсов... Но тогда сидите в Blend и работайте там, он специально для этого и предназначен.
SHE>Вообщем за время проекта имеем свой зверинец и здоровый зоопарк от коллег — все умники
То ли дело зоопарк яваскриптов, который не компилится, непонятно как тестируется имеет внутри три-четыре ветки под разные броузеры.
SHE>Или не всю, а скажем только 32-значный код ентого продукта. И что мне теперь — посимвольно переписывать с экрана? Или предусматривать каждый чих юзера и навешивать свои менюшки "еще по часу на правую кнопку" c одним пунктом "Copy to clipboard"? Ты просто засеки скока раз за день средний юзер тыкает CTRL-C/CTRL-V...
Мало. Очень мало. "Средний юзер" т.е. оператор сидит и долбит в формы данные. Кто с телефона, кто с каких-то бумаг. Никаких копи-пейстов. Всякие там манагеры и прочие сейлзы глядят в свои ненаглядные таблицы с графиками. Копипейстить там тоже особо негде.
Вообще, у вас ИМХО с юзабилити какие-то напряги. Клиент не должен ничего копи-пейстить. Вы спрашиваете " Вот надо мне ету инфу просто послать клиенту по мылу." — так я спрошу: как эти данные разослать всем клинентам? Пятьдесят тысяч копи-пейстов, не иначе. А только premium account-у? Сделать выборку и перекопипейстить их мыла
Если клиенту надо переслать по почте данные, то он должен тыцнуть мышкой: вот этим людям, на основании вооот этого шаблона послать вот эти данные. Всё. А заставлять пользователя копаться в аутлуке, искать какое мыло клиента(ой, а это он... или может оно сменилось? Вася, а ты не понишь, какое мыло этого... рыжего такого) — это, извините, бред.
YKU>>А как там этого достичь? Хаками js, попутно обходя грабельки особенностей разных броузеров? SHE>Все зависит от постановки задачи. Большинство решаемо без хаков. Большой выбор JS библиотек и разных cross-броузерных AJAX-tookit-ов позволяет забыть об особенностях этих самых броузеров. Ну и по-любому, HTML поддерживается гораздо большим количеством броузеров, чем Silverlight
Вы всё скинули в кучу. Изначально мы о чём говорили? "enterprise level приложения (back-office-а и т.д.)". Поэтому вопросы кто там кого подерживает нас не так и сильно волнуют.
Виндовые ie+ff+opera(вроде начала), safari поддерживают — этого обычно достаточно, что-бы покрыть любой корпоративный стандарт. Если заказчик вдруг сидит на линуксах с их броузерами(я, правда, такого не видел) — тогда да, увы, наверное флеш наш выбор.
Немного в сторону:В большинстве случаем я вообще не понимаю на кой чёрт им этот веб сдался: операторы сидят в офисе, если надо — им компы как угодно сконфигурят. "Заходить отовсюду" всё равно будут с личного ноута, ситуация "забежал в интернет кафе побыстрому заэпрувить инвойсы" выглядит несколько фантастичной. Но это лирика.
Тоже самое про "кинуть линк". "Кинуть линк" — это действительно надо для морды магазина("Зиночка, погляди какая штучка"), для back-office это нафиг никому не сдалось(если очень cильно надо — Navigation application поможет отцу). То же самое и про "открытие в новом окне"(а запретить открывать новые окна в некоторых обстоятельствах штука весьма полезная). Скопировать страничку себе да диск/добавить в закладки — это тоже полезно на уровне конечного клиента, забредшего на сайт, но никак не.
Re[54]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, gandjustas, Вы писали:
C>>>А ты думаешь это так просто? G>>Все равно придется писать код вычисления "эффективных ACL" и прав пользователя, причем именно в БД, чтобы не тащить кучу данных из базы. C>А данные всё равно будут подниматься перед выдачей их клиенту. Так что однофигственно.
Да ну? Клиенту для отображени ясовсем немного данных надо.
G>>А вызывать этот алгоритм в триггере на изменения и складывать результаты в таблицу гораздо проще. C>Ничуть. Особенно приятно, что количество таблиц примерно утраивается, ну и для ACLей ещё нужно имитировать "наследование", которое в БД нормальными средствами не делается.
Я говорю про таблицу для эффективных acl. Это будет 2-3 таблицы на всю базу.
C>Я уже ходил этим путём: http://www.rsdn.ru/forum/db/2396453.flat.aspx
Это совсем не тот путь.
C>>>Есть у тебя таблица типа с колонками "Имя", "Адрес", "Город", "Телефон". И рядом с ней поле ввода, и если туда ввести "Jo D 123", оно найдёт запись "John Doe, Some street, Some City, (123)-13241246". Мгновенно, точнее будет искать прямо пока ты вводишь. G>>С задержкой, равной латентности сети. C>С задержкой, минимально ограниченной латентностью сети. К примеру, если пользователей порядка 2000 и у каждого из них по 3 адреса — запрос уже будет выполняться ощутимое время. А ещё учитываем время на передачу результатов. На практике оно весьма тормозно получается.
Я че-то туплю. Данные уже есть на клиенте (в этой самой таблице), так что все будет моментально работать, не переживай.
C>>>Я же говорю — получается жуть. Меняется ACL у родителя — и нужно пересчитывать кэши всех детей. Не пропуская ничего, вдобавок. G>>Да, именно так. G>>И часто меняется ACL сильно родительской записи? И какова глубина иерархий? C>5-10 элементов. В паре вырожденных случаев около 50.
Ну это совсем немного.
C>В общем, очень и очень хрупкое решение.
Это потому что ты не умеешь его готовить.
C>>>Кроме того, сейчас у меня код — database independent. И работает под PostgreSQL, Oracle и (прости Боже!) MySQL. Как такое же на триггерах сделать? G>>Писать триггеры под разные базы, тем более их довольно небольшое количество. C>Во-во. И ACLи тоже. И запросы. И можно ли всё это сделать на MySQL с его странным языком триггеров и SP? А как быть с транзакциями —
Ну не пиши по MySQL, одной беслатной БД в арсенале вполне достаточно.
Если программа работает с любой БД, то или она очень простая, или не использует возможностей БД и греет воздух.
C>Спрашивается: ну и где наглядность L/ORM остаётся-то? Как обычно — только в теории?
Наглядности станет больше — станет меньше императивного кода.
C>>>Причём название группы должно быть хитро отсортировано (скажем, по весу). Последняя попытка дала килобайтный SQL-запрос. Хотя императивно оно пишется в десяток строк кода. G>>EF: G>>
G>>var q = from p in db.Products
G>> select {Product = p, Groups = p.Groups.OrderBy(g => g.Wheight)};
G>>
G>>Вот как-то так. C>Не-не. Это и я могу. Ты мне сделай так, чтоб оно список товаров выводило в том виде, в котором я его написал.
Большая разница чтоли?
var q = from p in db.Products
select {Product = p.Name, Groups = p.Groups.OrderBy(g => g.Wheight).Select(g => g.Name)};
А потом склеиваешь строки.
C>Оно реляционными методами эффективно не решается.
Что именно?
Как видишь запрос выше вполне решает. Или ты хочешь и строки склеивать в БД?
C>>>А ещё есть запросы со всякими running sums и delta'ами между строками... G>>Ну это тот самый случай когда императивный код в SQL рулит. G>>Хотя я бы в MS SQL сложные аггрегаты делал бы с помощью CLR расширений. C>Не знаю, может мне везёт, но у меня почему-то большинство таких отчётов.
Тебе везет или ты что-то не так делаешь.
Ингда выгоднее хранить дельты и использовать indexed\materialized view.
C>>>Так что не надо считать реляционную модель концом всего. Это неплохой подход, но далеко не единственный и далеко не всегда лучший. G>>Как раз реляционная работа с данными — самый лучший вариант работы с данными. C> C>Скажи это Гуглу, создателям Couch DB и языка K.
Couch DB — из другой оперы, там данные частично-структурированные.
G>>Вот только некоторые простые для императивной обработки вещи в SQL потребуют correlated subquery и офигенную сложность выполнения. C>Необязательно. Я могу взять нужные данные и руками по ним запустить обработку. На нормальном Turing-complete языке.
Ну собственно тебе никто не мешает это сделать. Ты можешь посчитать аггрегаты один раз и хранить их.
C>>>Ты ещё скажи "SQL отлично работает". Каким образом ты будешь обновлять связные кэши? G>>изменился last modified — кеш обновился. G>>Ты знаешь как кеширование в HTTP работает? C>"last modified" _на_ _что_?
На запрос.
C>>>А как насчёт инкрементальности? Будем все 500 килобайт результатов каждого запроса перегружать пару раз в пару секунд? G>>А зачем их перезагружать? Они реально пару раз в секунду меняются? G>>Повысить гранулярность можно, тогда придется гораздо меньше перезагружать. C>??? C>Повышаем гранулярность — и перегружаем всю "гранулу" при её изменении. Только объём увеличится.
Не тупи. Высокая гранулярность — более "мелкие" гранулы.
Re[55]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>А данные всё равно будут подниматься перед выдачей их клиенту. Так что однофигственно. G>Да ну? Клиенту для отображени ясовсем немного данных надо.
Опять же говорю — не немного.
C>>Ничуть. Особенно приятно, что количество таблиц примерно утраивается, ну и для ACLей ещё нужно имитировать "наследование", которое в БД нормальными средствами не делается. G>Я говорю про таблицу для эффективных acl. Это будет 2-3 таблицы на всю базу.
Как на них констрейнты повесить?
C>>Я уже ходил этим путём: http://www.rsdn.ru/forum/db/2396453.flat.aspx
G> Это совсем не тот путь.
Именно тот. По-другому не получается.
C>>С задержкой, минимально ограниченной латентностью сети. К примеру, если пользователей порядка 2000 и у каждого из них по 3 адреса — запрос уже будет выполняться ощутимое время. А ещё учитываем время на передачу результатов. На практике оно весьма тормозно получается. G>Я че-то туплю. Данные уже есть на клиенте (в этой самой таблице), так что все будет моментально работать, не переживай.
В таблице могут быть не совсем все данные.
G>>>И часто меняется ACL сильно родительской записи? И какова глубина иерархий? C>>5-10 элементов. В паре вырожденных случаев около 50. G>Ну это совсем немного.
Более чем.
C>>В общем, очень и очень хрупкое решение. G>Это потому что ты не умеешь его готовить.
Умею. Оно уже было так сделано. Передалал.
C>>Во-во. И ACLи тоже. И запросы. И можно ли всё это сделать на MySQL с его странным языком триггеров и SP? А как быть с транзакциями — G>Ну не пиши по MySQL, одной беслатной БД в арсенале вполне достаточно. G>Если программа работает с любой БД, то или она очень простая, или не использует возможностей БД и греет воздух.
Это просто с твоим архаичным подходом с кашей непонятно каких триггеров, UDF, кэширующих таблиц, странных кэшей, непонятных батчей так не получается. А с современными ORM — всё просто и без проблем делается.
C>>Спрашивается: ну и где наглядность L/ORM остаётся-то? Как обычно — только в теории? G>Наглядности станет больше — станет меньше императивного кода.
Ага. Триггеры — это у нас уже не императивный подход?
C>>Не-не. Это и я могу. Ты мне сделай так, чтоб оно список товаров выводило в том виде, в котором я его написал. G>Большая разница чтоли? G>
G>var q = from p in db.Products
G> select {Product = p.Name, Groups = p.Groups.OrderBy(g => g.Wheight).Select(g => g.Name)};
G>
G>А потом склеиваешь строки.
Опять неверно. Нужно найти все _комбинации_ групп.
C>>Не знаю, может мне везёт, но у меня почему-то большинство таких отчётов. G>Тебе везет или ты что-то не так делаешь. G>Ингда выгоднее хранить дельты и использовать indexed\materialized view.
А мне не надо делать никаких видов под отдельные запросы, ничего. В БД хранятся ТОЛЬКО данные и НИКАКОЙ логики.
Single Responsibility Principle, однако.
C>>Скажи это Гуглу, создателям Couch DB и языка K. G>Couch DB — из другой оперы, там данные частично-структурированные.
И что?
G>>>Вот только некоторые простые для императивной обработки вещи в SQL потребуют correlated subquery и офигенную сложность выполнения. C>>Необязательно. Я могу взять нужные данные и руками по ним запустить обработку. На нормальном Turing-complete языке. G>Ну собственно тебе никто не мешает это сделать. Ты можешь посчитать аггрегаты один раз и хранить их.
И обновлять их ВСЕ при каждом изменении. Даже если часть аггрегатов нужна раз в пятилетку.
G>>>Ты знаешь как кеширование в HTTP работает? C>>"last modified" _на_ _что_? G>На запрос.
На какой?
Ты видел поле с расписанием на скриншоте? Так вот, он зависит что-то около от 200 таблиц. Другой вид данных зависит от примерно такого же числа таблиц, но чуть-чуть других.
ЧТО мы будем слушать-то?
C>>Повышаем гранулярность — и перегружаем всю "гранулу" при её изменении. Только объём увеличится. G>Не тупи. Высокая гранулярность — более "мелкие" гранулы.
А, ну ладно. Тогда проблемы с зависимостями. Скажем, пользователя надо показывать "недоступным", если он в это время запланировал meeting. Планирование meeting'ов и показ расписания — в очень разных частях БД.
Так что если мы слушаем только
Sapienti sat!
Re[6]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, yoriсk.kiev.ua, Вы писали:
YKU>Повторюсь: менять дизайн — это копейки. Если только вы не юзабелист/дизайнер интерфейсов... Но тогда сидите в Blend и работайте там, он специально для этого и предназначен.
Как можно говорить об интерфейсе не упоминая дизайн?? Вы этим не занимаетесь вообще или чувствуете недостаточно компетентным чтобы обсуждать? Не каждая контора может себе позволить дизайнера как отдельную сущность.
YKU>То ли дело зоопарк яваскриптов, который не компилится, непонятно как тестируется имеет внутри три-четыре ветки под разные броузеры.
Все уже сделано за вас — prototype/jquery/extjs/другая по вкусу библиотека вам в руки.
YKU>Вообще, у вас ИМХО с юзабилити какие-то напряги. Клиент не должен ничего копи-пейстить.
Смотря какой клиент, смотря с какой информацией работает. Нет никаких напрягов — просто упомянул одним из достоинств HTMLя то, что с ним нештатно доступны дополнительные функции, к которым пользователь привык и уже воспринимает как должное. Попробуйте выделить фрагмент в броузере и кликнуть правой кнопкой мыши — вот вам печать, перевод, сохранить, избранное, поиск, експорт + всякие там акселераторы (IE8) на выбор и т.д.
С SL большинство функций и приятных фенечек броузера становится недоступной (совсем не значит что невостребованной!).
Вам все ето не надо? Все ето можно сделать на SL? сомневаюсь, но флаг вам в руки
YKU>Вы всё скинули в кучу.
Зато у вас никакой кучи и нет. Да, с SL вы пишите только на одном языке и ето большой плюс, но етим вы и ограничены. Песочница Silverlight-а еще по-детски мала (поздравляю, в последней версии появился диалог SaveAs, ради интереса пробегитесь по форумам посмотрите какие воркароунды до етого предлагались...). Если вы чуствуете себя в ней комфортно — прекрасно, рад за вас и ваших пользователей. Я же пока воспользуюсь той функциональностью и богаством выбора, который предоставляет современный web, НЕ ИСКЛЮЧАЯ возможности реализации каких-то элементов на SL. И ето намного выгоднее позиция и для продукта и для его пользователей, чем постоянно спотыкаться, локти кусать и жить в ожидании — ну когдааааа же Microsoft ето сделает и то доделает...
Re[56]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, gandjustas, Вы писали:
C>>>А данные всё равно будут подниматься перед выдачей их клиенту. Так что однофигственно. G>>Да ну? Клиенту для отображени ясовсем немного данных надо. C>Опять же говорю — не немного.
То что ты показал на скриншоте требует не более 1 мб. А при умном подходе и того меньше.
C>>>Я уже ходил этим путём: http://www.rsdn.ru/forum/db/2396453.flat.aspx
G>> Это совсем не тот путь. C>Именно тот. По-другому не получается.
Соболезную. Но все равно не тот путь.
C>>>С задержкой, минимально ограниченной латентностью сети. К примеру, если пользователей порядка 2000 и у каждого из них по 3 адреса — запрос уже будет выполняться ощутимое время. А ещё учитываем время на передачу результатов. На практике оно весьма тормозно получается. G>>Я че-то туплю. Данные уже есть на клиенте (в этой самой таблице), так что все будет моментально работать, не переживай. C>В таблице могут быть не совсем все данные.
А зачем искать по данным, которые визуально не отображаются?
C>>>В общем, очень и очень хрупкое решение. G>>Это потому что ты не умеешь его готовить. C>Умею. Оно уже было так сделано. Передалал.
Если получилось очень хрупкое решение — значит не умеешь.
Весь веб так работает. Посмотри на сервисы гугла.
C>>>Во-во. И ACLи тоже. И запросы. И можно ли всё это сделать на MySQL с его странным языком триггеров и SP? А как быть с транзакциями — G>>Ну не пиши по MySQL, одной беслатной БД в арсенале вполне достаточно. G>>Если программа работает с любой БД, то или она очень простая, или не использует возможностей БД и греет воздух. C>Это просто с твоим архаичным подходом с кашей непонятно каких триггеров, UDF, кэширующих таблиц, странных кэшей, непонятных батчей так не получается. А с современными ORM — всё просто и без проблем делается.
Не надо придавать эмоциональную окраску техническим вопросом. Подучись немного и триггеры, UDF и кеширующие таблицы станут для тебя вполне нормальными.
А в современными ORM все что удвлось тебе сделать — приложение, которому для старта требуется 30 метров выкачать.
При таком раскладе легче remote desktop использовать.
C>>>Спрашивается: ну и где наглядность L/ORM остаётся-то? Как обычно — только в теории? G>>Наглядности станет больше — станет меньше императивного кода. C>Ага. Триггеры — это у нас уже не императивный подход?
Нет, с чего бы?
Триггеры это просто функции, которые будут вызываться неявно. Внутри уже пишешь как захочешь.
G>>>>Вот только некоторые простые для императивной обработки вещи в SQL потребуют correlated subquery и офигенную сложность выполнения. C>>>Необязательно. Я могу взять нужные данные и руками по ним запустить обработку. На нормальном Turing-complete языке. G>>Ну собственно тебе никто не мешает это сделать. Ты можешь посчитать аггрегаты один раз и хранить их. C>И обновлять их ВСЕ при каждом изменении. Даже если часть аггрегатов нужна раз в пятилетку.
А с чего ты взял что все обновлять надо? Ты же знаешь конкретные изменения, вот и обновляй зименившиеся аггрегаты.
И это все равно будет дешевле, чем пересчитывть аггрегаты при запросах.
G>>>>Ты знаешь как кеширование в HTTP работает? C>>>"last modified" _на_ _что_? G>>На запрос. C>На какой?
На любой.
C>Ты видел поле с расписанием на скриншоте? Так вот, он зависит что-то около от 200 таблиц. Другой вид данных зависит от примерно такого же числа таблиц, но чуть-чуть других.
Да хоть от 1000.
C>ЧТО мы будем слушать-то?
Ты же заешь какие действия толькователя повлияют на таблицу, вот и пусть эти действия вызывают обновления last modified для таблицы.
Незачем на клиента тащить всю схему данных.
C>>>Повышаем гранулярность — и перегружаем всю "гранулу" при её изменении. Только объём увеличится. G>>Не тупи. Высокая гранулярность — более "мелкие" гранулы. C>А, ну ладно. Тогда проблемы с зависимостями. Скажем, пользователя надо показывать "недоступным", если он в это время запланировал meeting. Планирование meeting'ов и показ расписания — в очень разных частях БД.
См выше.
Re[57]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>Опять же говорю — не немного. G>То что ты показал на скриншоте требует не более 1 мб. А при умном подходе и того меньше.
Угу. А потом roundtrip на каждый щелчок.
G>>>Я че-то туплю. Данные уже есть на клиенте (в этой самой таблице), так что все будет моментально работать, не переживай. C>>В таблице могут быть не совсем все данные. G>А зачем искать по данным, которые визуально не отображаются?
Чтобы отобразить их.
C>>Умею. Оно уже было так сделано. Передалал. G>Если получилось очень хрупкое решение — значит не умеешь. G>Весь веб так работает. Посмотри на сервисы гугла.
У Гугла очень простые сервисы, которые обслуживает кластер из сотен тысяч машин.
Вдобавок, часть приложений у них таки по моей схеме работает. К примеру, GMail c Google Gears (который в offline работает, да). Или их электронная таблица — они там отправляют на сервер только лог измений, а почти все расчёты идут на клиенте (вот ведь, никто не сказал кретинам оттуда, что проще каждый click на сервер отправлять!).
Так что мимо.
C>>Это просто с твоим архаичным подходом с кашей непонятно каких триггеров, UDF, кэширующих таблиц, странных кэшей, непонятных батчей так не получается. А с современными ORM — всё просто и без проблем делается. G>Не надо придавать эмоциональную окраску техническим вопросом. Подучись немного и триггеры, UDF и кеширующие таблицы станут для тебя вполне нормальными.
Не, до такого состояния разума я не дойду. Я видел в кого превращаются профессиональные DBA, спасибо.
G>А в современными ORM все что удвлось тебе сделать — приложение, которому для старта требуется 30 метров выкачать.
Не 30 Мб, я же уже сказал это. Меньше 5Мб — около 30 секунд на медленном соединении.
А после начальной загрузки можно и с модема работать, кстати. Без всяких проблем ВООБЩЕ. Реально спасло пару раз, когда из каналов связи был только тормозной и дорогой GPRS.
G>При таком раскладе легче remote desktop использовать.
Не проще.
G>>>Наглядности станет больше — станет меньше императивного кода. C>>Ага. Триггеры — это у нас уже не императивный подход? G>Нет, с чего бы?
Да, с того бы.
G>Триггеры это просто функции, которые будут вызываться неявно. Внутри уже пишешь как захочешь.
Угу, именно. Это процедуры, которые запускаются при модификации данных. В них ничерта нет от реляционности — это просто вариант AOP.
C>>И обновлять их ВСЕ при каждом изменении. Даже если часть аггрегатов нужна раз в пятилетку. G>А с чего ты взял что все обновлять надо? Ты же знаешь конкретные изменения, вот и обновляй зименившиеся аггрегаты.
Нет, я не знаю конкретные изменения.
G>И это все равно будет дешевле, чем пересчитывть аггрегаты при запросах.
Не будет.
G>>>>>Ты знаешь как кеширование в HTTP работает? C>>>>"last modified" _на_ _что_? G>>>На запрос. C>>На какой? G>На любой.
В том числе, и на запрос "выбери мне первое число, которое не представимо в виде суммы двух простых чисел"?
C>>Ты видел поле с расписанием на скриншоте? Так вот, он зависит что-то около от 200 таблиц. Другой вид данных зависит от примерно такого же числа таблиц, но чуть-чуть других. G>Да хоть от 1000.
Ну да. Чего мелочиться, пусть хоть миллион будет!
C>>ЧТО мы будем слушать-то? G>Ты же заешь какие действия толькователя повлияют на таблицу, вот и пусть эти действия вызывают обновления last modified для таблицы.
НЕТ, я НЕ ЗНАЮ какие действия толькователя повлияют на таблицу.
Более того, МНЕ ЭТО НЕ НУЖНО знать. А вот тебе придётся руками отслеживать ВСЕ неявные связи, иначе появятся возможности получения неконсистентной информации?
Ещё насчёт неконсистентности — у тебя ещё будут и несколько параллельных "отслеживателей", слушающих события. Причём порядок их отработки — ничем не определён. Так что запросто полчаем сценарий, когда в одной части окна данные обновятся, а в другой части будут висеть старые.
Стоит ли говорить, что у меня ещё и ВСЁ транзакционно-безопасно и гарантирован строгий порядок доставки событий?
G>Незачем на клиента тащить всю схему данных.
Почему?
Sapienti sat!
Re[58]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, gandjustas, Вы писали:
C>>>Опять же говорю — не немного. G>>То что ты показал на скриншоте требует не более 1 мб. А при умном подходе и того меньше. C>Угу. А потом roundtrip на каждый щелчок.
Это не так страшно, тем более при кешировании результатов.
C>>>Умею. Оно уже было так сделано. Передалал. G>>Если получилось очень хрупкое решение — значит не умеешь. G>>Весь веб так работает. Посмотри на сервисы гугла. C>У Гугла очень простые сервисы, которые обслуживает кластер из сотен тысяч машин.
Заметил такую тенденцию на формуме — неудачные технические решения оправдываются сложностью задачи и наоборот удачные решения объявляют чуть ли не тривиальными вещами.
Даю руку на отсечение что любой из гугловых сервисов сложнее того что пишешь ты.
C>Вдобавок, часть приложений у них таки по моей схеме работает. К примеру, GMail c Google Gears (который в offline работает, да). Или их электронная таблица — они там отправляют на сервер только лог измений, а почти все расчёты идут на клиенте (вот ведь, никто не сказал кретинам оттуда, что проще каждый click на сервер отправлять!).
рассчеты на клиенте абсолютно ортогональны тому что тут обсуждается.
C>>>Это просто с твоим архаичным подходом с кашей непонятно каких триггеров, UDF, кэширующих таблиц, странных кэшей, непонятных батчей так не получается. А с современными ORM — всё просто и без проблем делается. G>>Не надо придавать эмоциональную окраску техническим вопросом. Подучись немного и триггеры, UDF и кеширующие таблицы станут для тебя вполне нормальными. C>Не, до такого состояния разума я не дойду. Я видел в кого превращаются профессиональные DBA, спасибо.
Меньше эмоций, разум чище будет.
G>>А в современными ORM все что удвлось тебе сделать — приложение, которому для старта требуется 30 метров выкачать. C>Не 30 Мб, я же уже сказал это. Меньше 5Мб — около 30 секунд на медленном соединении.
Ого, хорошее у тебя медленное соединение. У меня ADSL в лучшие времена не так быстро работал.
G>>>>Наглядности станет больше — станет меньше императивного кода. C>>>Ага. Триггеры — это у нас уже не императивный подход? G>>Нет, с чего бы? C>Да, с того бы.
Ну так обоснуй.
G>>Триггеры это просто функции, которые будут вызываться неявно. Внутри уже пишешь как захочешь. C>Угу, именно. Это процедуры, которые запускаются при модификации данных. В них ничерта нет от реляционности — это просто вариант AOP.
А чем aop противоречит реляцонности?
Это вообще разные категории.
C>>>И обновлять их ВСЕ при каждом изменении. Даже если часть аггрегатов нужна раз в пятилетку. G>>А с чего ты взял что все обновлять надо? Ты же знаешь конкретные изменения, вот и обновляй зименившиеся аггрегаты. C>Нет, я не знаю конкретные изменения.
Такого не бывает. Ты же программу пишешь и обрабатываешь конкретные действия пользователей, которые соответствуют конкретным сценариям работы системы, которые приводят к конкретным изменениям данных.
Другое дело что у тебя код построен так что ты не можешь из его массы выделить эти самые сценарии, но это уже проблема кода.
G>>И это все равно будет дешевле, чем пересчитывть аггрегаты при запросах. C>Не будет.
Будет. Кроме того с точки зрения пользователя повысится производительность.
Пользователь желая увидеть данные готов ждать гораздо меньше, чем при желании данные изменить.
Например заходя на сайт хочется видеть страницу сразу, а постя сообщение на форум подождать пару секунд — впнолне терпимо.
G>>>>>>Ты знаешь как кеширование в HTTP работает? C>>>>>"last modified" _на_ _что_? G>>>>На запрос. C>>>На какой? G>>На любой. C>В том числе, и на запрос "выбери мне первое число, которое не представимо в виде суммы двух простых чисел"?
Конечно, а чем он хуже других?
Только имеет ли смысл вообще запрашивать что-либо в таком случае?
C>>>ЧТО мы будем слушать-то? G>>Ты же заешь какие действия толькователя повлияют на таблицу, вот и пусть эти действия вызывают обновления last modified для таблицы. C>НЕТ, я НЕ ЗНАЮ какие действия толькователя повлияют на таблицу.
Это я уже понял.
C>Более того, МНЕ ЭТО НЕ НУЖНО знать. А вот тебе придётся руками отслеживать ВСЕ неявные связи, иначе появятся возможности получения неконсистентной информации?
Я не создаю неявных связей, у меня все связи явные.
C>Ещё насчёт неконсистентности — у тебя ещё будут и несколько параллельных "отслеживателей", слушающих события. Причём порядок их отработки — ничем не определён. Так что запросто полчаем сценарий, когда в одной части окна данные обновятся, а в другой части будут висеть старые.
И с чего они висеть там останутся?
C>Стоит ли говорить, что у меня ещё и ВСЁ транзакционно-безопасно и гарантирован строгий порядок доставки событий? И что тебе с этого? Длинее и толще?
G>>Незачем на клиента тащить всю схему данных. C>Почему?
Потому что это лишний расход трафика и бесполезное нагревание воздуха серверной.
Re[59]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>Угу. А потом roundtrip на каждый щелчок. G>Это не так страшно, тем более при кешировании результатов.
1) Что кэшировать-то? Вот я нажал на ячейку — и мне надо показать подробные детали для неё. Шансы что я нажму на неё второй раз — не особо велики.
2) Как инвалидировать будем-с?
C>>У Гугла очень простые сервисы, которые обслуживает кластер из сотен тысяч машин. G>Заметил такую тенденцию на формуме — неудачные технические решения оправдываются сложностью задачи и наоборот удачные решения объявляют чуть ли не тривиальными вещами. G>Даю руку на отсечение что любой из гугловых сервисов сложнее того что пишешь ты.
Давай.
C>>Вдобавок, часть приложений у них таки по моей схеме работает. К примеру, GMail c Google Gears (который в offline работает, да). Или их электронная таблица — они там отправляют на сервер только лог измений, а почти все расчёты идут на клиенте (вот ведь, никто не сказал кретинам оттуда, что проще каждый click на сервер отправлять!). G>рассчеты на клиенте абсолютно ортогональны тому что тут обсуждается.
Ничуть. Вообще, GMail работает ровно так же, как и мой код. С той лишь разницей, что они вместо H/ORM используют какое-то своё кластерное хранилище.
Там ровно так же на клиенте хранится кэш данных, с которым работает JavaScript-код. GMail ровно так же как и я вместо прямых запросов "дай данные для этой ячейки" использует подход "загрузить и положить в кэш данные", которые уже и отобржаются.
C>>Не 30 Мб, я же уже сказал это. Меньше 5Мб — около 30 секунд на медленном соединении. G>Ого, хорошее у тебя медленное соединение. У меня ADSL в лучшие времена не так быстро работал.
Это где-то скорость 1.5Мбит. Действительно, не совсем медленное.
G>>>Триггеры это просто функции, которые будут вызываться неявно. Внутри уже пишешь как захочешь. C>>Угу, именно. Это процедуры, которые запускаются при модификации данных. В них ничерта нет от реляционности — это просто вариант AOP. G>А чем aop противоречит реляцонности?
Вообще-то, да. Он к ней неприменим. Реляционная алгебра — это просто алгебра работы с множествами, которая позволяет делать гибкие структурированные хранилища.
Хранимые процедуры, триггеры, CTE — уже не имеют никакого отношения к реляционной алгебре. Соответственно, глупо утверждать что программа с большим числом хранимок и триггеров более "реляционна", чем программа с H/ORM.
Пропоненты L/ORM именно так пока и делают.
G>>>А с чего ты взял что все обновлять надо? Ты же знаешь конкретные изменения, вот и обновляй зименившиеся аггрегаты. C>>Нет, я не знаю конкретные изменения. G>Такого не бывает. Ты же программу пишешь и обрабатываешь конкретные действия пользователей, которые соответствуют конкретным сценариям работы системы, которые приводят к конкретным изменениям данных.
Ещё как бывает со сложными моделями. У меня сейчас более тысячи разных операций. Для каждой операции в твоём подходе необходимо знать как она повлияет на всё остальное.
Может ты не работал с большими и сложными моделями?
G>Будет. Кроме того с точки зрения пользователя повысится производительность. G>Пользователь желая увидеть данные готов ждать гораздо меньше, чем при желании данные изменить. G>Например заходя на сайт хочется видеть страницу сразу, а постя сообщение на форум подождать пару секунд — впнолне терпимо.
Ты не учитываешь, что некоторые изменения должны делаються очень быстро. Если координатор, который должен распределить пару тысяч смен, должен по 10 секунд ждать на каждую операцию — он придёт к тебе домой и тебя застрелит.
C>>>>На какой? G>>>На любой. C>>В том числе, и на запрос "выбери мне первое число, которое не представимо в виде суммы двух простых чисел"? G>Конечно, а чем он хуже других?
Нууу...
G>Только имеет ли смысл вообще запрашивать что-либо в таком случае?
А вот надо. Как делать будем?
C>>Более того, МНЕ ЭТО НЕ НУЖНО знать. А вот тебе придётся руками отслеживать ВСЕ неявные связи, иначе появятся возможности получения неконсистентной информации? G>Я не создаю неявных связей, у меня все связи явные.
Я говорю не про FK. Я уже привёл пример, когда изменение одного кусочка данных повляет на другой, не связанный напрямую с ним.
C>>Ещё насчёт неконсистентности — у тебя ещё будут и несколько параллельных "отслеживателей", слушающих события. Причём порядок их отработки — ничем не определён. Так что запросто полчаем сценарий, когда в одной части окна данные обновятся, а в другой части будут висеть старые. G>И с чего они висеть там останутся?
А не прошёл HTTP-запрос. Пакетик потерялся, и он ждёт retransmit'а. Или файрвол решил задержать ответ до проверки нет ли в нём вирусов.
Оба случая вполне реальные.
C>>Стоит ли говорить, что у меня ещё и ВСЁ транзакционно-безопасно и гарантирован строгий порядок доставки событий? G> И что тебе с этого? Длинее и толще?
Угу.
G>>>Незачем на клиента тащить всю схему данных. C>>Почему? G>Потому что это лишний расход трафика и бесполезное нагревание воздуха серверной.
Нет. Лишний расход траффика — у тебя. У меня сейчас дневной расход на приложение — около 10Мб. 5Мб на начальную загрузку (надо бы её оптимизировать...), а дальше считанные байты на трансляцию изменений.
Т.е. оно реально может использоваться на модеме.
Для твоей модели оно недостижимо.
Sapienti sat!
Re[60]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, gandjustas, Вы писали:
C>>>Угу. А потом roundtrip на каждый щелчок. G>>Это не так страшно, тем более при кешировании результатов. C>1) Что кэшировать-то? Вот я нажал на ячейку — и мне надо показать подробные детали для неё. Шансы что я нажму на неё второй раз — не особо велики.
Вот подробные детали и кешируй. Даже если второй раз запрошено никогда не будет это не даст заметного оверхеда. Причем кеш ответов не вносит оверхед в отличе от кеширования данных.
C>2) Как инвалидировать будем-с?
last modified
C>>>Вдобавок, часть приложений у них таки по моей схеме работает. К примеру, GMail c Google Gears (который в offline работает, да). Или их электронная таблица — они там отправляют на сервер только лог измений, а почти все расчёты идут на клиенте (вот ведь, никто не сказал кретинам оттуда, что проще каждый click на сервер отправлять!). G>>рассчеты на клиенте абсолютно ортогональны тому что тут обсуждается. C>Ничуть. Вообще, GMail работает ровно так же, как и мой код. С той лишь разницей, что они вместо H/ORM используют какое-то своё кластерное хранилище.
С чего ты взял? Исходники видел?
C>Там ровно так же на клиенте хранится кэш данных, с которым работает JavaScript-код. GMail ровно так же как и я вместо прямых запросов "дай данные для этой ячейки" использует подход "загрузить и положить в кэш данные", которые уже и отобржаются.
Это всегда так будет. Отличие в том, что GMail получает данные необходимые для отображения, а ты тянешь на клиента модель из базы.
C>>>Не 30 Мб, я же уже сказал это. Меньше 5Мб — около 30 секунд на медленном соединении. G>>Ого, хорошее у тебя медленное соединение. У меня ADSL в лучшие времена не так быстро работал. C>Это где-то скорость 1.5Мбит. Действительно, не совсем медленное.
Интересно, откуда латентность в 200 мс на таких каналах?
C>Хранимые процедуры, триггеры, CTE — уже не имеют никакого отношения к реляционной алгебре. Соответственно, глупо утверждать что программа с большим числом хранимок и триггеров более "реляционна", чем программа с H/ORM.
Как раз можно, томому что теже триггеры и CTE работают именно с реляционными данными, тогда как H/ORM хочет сделать вид что работа идет с объектами.
G>>>>А с чего ты взял что все обновлять надо? Ты же знаешь конкретные изменения, вот и обновляй зименившиеся аггрегаты. C>>>Нет, я не знаю конкретные изменения. G>>Такого не бывает. Ты же программу пишешь и обрабатываешь конкретные действия пользователей, которые соответствуют конкретным сценариям работы системы, которые приводят к конкретным изменениям данных. C>Ещё как бывает со сложными моделями. У меня сейчас более тысячи разных операций. Для каждой операции в твоём подходе необходимо знать как она повлияет на всё остальное.
Не знаю как тебе, а мне не удавалось писать программы в которых я не знаю что происходит.
И для каждого сценария я могу сказать к каким изменениям он приводит.
C>Может ты не работал с большими и сложными моделями?
Работал
G>>Будет. Кроме того с точки зрения пользователя повысится производительность. G>>Пользователь желая увидеть данные готов ждать гораздо меньше, чем при желании данные изменить. G>>Например заходя на сайт хочется видеть страницу сразу, а постя сообщение на форум подождать пару секунд — впнолне терпимо. C>Ты не учитываешь, что некоторые изменения должны делаються очень быстро. Если координатор, который должен распределить пару тысяч смен, должен по 10 секунд ждать на каждую операцию — он придёт к тебе домой и тебя застрелит.
Ну да, выдумывание небылиц — хороший способ обоснования свой позиции, с чего ты взял 10 секунд?
Даже если взять того же оператора и представить что пересчет аггрегатов в запросе выполняется в 100 раз быстрее 0.1 секунду, то на отображение 10000 записей ему придется ждать около 20 минут. И это прижедтся испытать каждому пользователю, который попытается просмотреть расписание.
G>>Только имеет ли смысл вообще запрашивать что-либо в таком случае? C>А вот надо. Как делать будем?
C>>>Более того, МНЕ ЭТО НЕ НУЖНО знать. А вот тебе придётся руками отслеживать ВСЕ неявные связи, иначе появятся возможности получения неконсистентной информации? G>>Я не создаю неявных связей, у меня все связи явные. C>Я говорю не про FK. Я уже привёл пример, когда изменение одного кусочка данных повляет на другой, не связанный напрямую с ним.
И что? Ты создавая программу не знаешь какие действия на какие данные повлияют?
C>>>Ещё насчёт неконсистентности — у тебя ещё будут и несколько параллельных "отслеживателей", слушающих события. Причём порядок их отработки — ничем не определён. Так что запросто полчаем сценарий, когда в одной части окна данные обновятся, а в другой части будут висеть старые. G>>И с чего они висеть там останутся? C>А не прошёл HTTP-запрос. Пакетик потерялся, и он ждёт retransmit'а. Или файрвол решил задержать ответ до проверки нет ли в нём вирусов.
Этона каталах, которые по 1,5 мбит выдают? Сам в это веришь?
C>Оба случая вполне реальные.
Ну встретить динозавра тоже вполне реально, даже с вероятностью отличной от нуля.
G>>>>Незачем на клиента тащить всю схему данных. C>>>Почему? G>>Потому что это лишний расход трафика и бесполезное нагревание воздуха серверной. C>Нет. Лишний расход траффика — у тебя. У меня сейчас дневной расход на приложение — около 10Мб. 5Мб на начальную загрузку (надо бы её оптимизировать...), а дальше считанные байты на трансляцию изменений.
А в моем подходе не будет начальной загрузки и теже 5 метров будут растянуты по времени. И потом тоже будут "считанные байты" на изменения.
C>Т.е. оно реально может использоваться на модеме.
Я плакал
C>Для твоей модели оно недостижимо.
Ну я как раз через GPRS часто в интернете сижу. Если бы мне кто-нибудь предложил скачать 5 метров просто чтобы начать пользоваться программой, то я бы сразу послал такой сервис.
Короче хватит практиковаться в выдумывании небылиц. Адекватного описания преимуществ твоего подхода не видно, а все что есть вполне делается и без h\orm.
Re[61]: Фреймфорк для разработки Веб и десктоп-приложений на
Здравствуйте, gandjustas, Вы писали:
C>>1) Что кэшировать-то? Вот я нажал на ячейку — и мне надо показать подробные детали для неё. Шансы что я нажму на неё второй раз — не особо велики. G>Вот подробные детали и кешируй. Даже если второй раз запрошено никогда не будет это не даст заметного оверхеда. Причем кеш ответов не вносит оверхед в отличе от кеширования данных.
Торможение в первый раз — уже неприемлимо.
C>>2) Как инвалидировать будем-с? G>last modified
Это требует _каждый_ _раз_ делать запрос на сервер при нажатии на ячейку. Пофиг что оно вернёт "304 Not Modified" — всё равно нужен отдельный запрос.
C>>Ничуть. Вообще, GMail работает ровно так же, как и мой код. С той лишь разницей, что они вместо H/ORM используют какое-то своё кластерное хранилище. G>С чего ты взял? Исходники видел?
Нет. Презентации о его архитектуре.
C>>Там ровно так же на клиенте хранится кэш данных, с которым работает JavaScript-код. GMail ровно так же как и я вместо прямых запросов "дай данные для этой ячейки" использует подход "загрузить и положить в кэш данные", которые уже и отобржаются. G>Это всегда так будет. Отличие в том, что GMail получает данные необходимые для отображения, а ты тянешь на клиента модель из базы.
Мимо. GMail точно так же загружает сразу больше данных, чем видно. Просто с EMail'ом всё просто.
А вот их приложение с электронной таблицей вообще почти всё на клиенте работает.
G>>>Ого, хорошее у тебя медленное соединение. У меня ADSL в лучшие времена не так быстро работал. C>>Это где-то скорость 1.5Мбит. Действительно, не совсем медленное. G>Интересно, откуда латентность в 200 мс на таких каналах?
Из-за конечной скорости света, глюкодромных ADSL и промежуточных хостов. Латентность имеет мало отношения к пропускной способности канала.
C>>Хранимые процедуры, триггеры, CTE — уже не имеют никакого отношения к реляционной алгебре. Соответственно, глупо утверждать что программа с большим числом хранимок и триггеров более "реляционна", чем программа с H/ORM. G>Как раз можно, томому что теже триггеры и CTE работают именно с реляционными данными, тогда как H/ORM хочет сделать вид что работа идет с объектами.
Нет, H/ORM работает с объектным представлением реляционных данных.
Сам по себе H/ORM так же "реляционен" как и голый SQL.
C>>Ещё как бывает со сложными моделями. У меня сейчас более тысячи разных операций. Для каждой операции в твоём подходе необходимо знать как она повлияет на всё остальное. G>Не знаю как тебе, а мне не удавалось писать программы в которых я не знаю что происходит.
Ты знаешь, когда у тебя в программе на C# запускается GC?
Вот и мне неинтересно знать.
G>И для каждого сценария я могу сказать к каким изменениям он приводит.
Я тоже. Если специально посмотреть. Но зачем?
C>>Ты не учитываешь, что некоторые изменения должны делаються очень быстро. Если координатор, который должен распределить пару тысяч смен, должен по 10 секунд ждать на каждую операцию — он придёт к тебе домой и тебя застрелит. G>Ну да, выдумывание небылиц — хороший способ обоснования свой позиции, с чего ты взял 10 секунд?
Даже пара секунд — уже много. Уже даже доли секунды — слишком много.
G>Даже если взять того же оператора и представить что пересчет аггрегатов в запросе выполняется в 100 раз быстрее 0.1 секунду, то на отображение 10000 записей ему придется ждать около 20 минут. И это прижедтся испытать каждому пользователю, который попытается просмотреть расписание.
Ты забываешь, что в том виде, который смотрит координатор никакие сложные аггрегаты не считаются.
C>>Я говорю не про FK. Я уже привёл пример, когда изменение одного кусочка данных повляет на другой, не связанный напрямую с ним. G>И что? Ты создавая программу не знаешь какие действия на какие данные повлияют?
Не знаю. Поэтому и сделал систему, где мне и знать это необязательно.
C>>А не прошёл HTTP-запрос. Пакетик потерялся, и он ждёт retransmit'а. Или файрвол решил задержать ответ до проверки нет ли в нём вирусов. G>Этона каталах, которые по 1,5 мбит выдают? Сам в это веришь?
Я же говорю — случаи реальные. Точнее, достоверно случившиеся. Вот буквально вчера пользователь пожаловался, что файл из системы документ-менеджмента в приложении не могут закачать. Оказалось, что излишне прыткий антивирус перехватил обращение, и не отдавал последний байтик пока не проверит всё тело (защищённое HTTPS — чего он там сканировал?). Чем вызывал таймаут в приложении.
C>>Нет. Лишний расход траффика — у тебя. У меня сейчас дневной расход на приложение — около 10Мб. 5Мб на начальную загрузку (надо бы её оптимизировать...), а дальше считанные байты на трансляцию изменений. G> G>А в моем подходе не будет начальной загрузки и теже 5 метров будут растянуты по времени. И потом тоже будут "считанные байты" на изменения.
Не будут. У тебя загрузка одного вида займёт в лучшем случае килобайт 500. А их переключают кучу десятков раз в день.
C>>Т.е. оно реально может использоваться на модеме. G> G>Я плакал
Плачь. Требование реально.
C>>Для твоей модели оно недостижимо. G>Ну я как раз через GPRS часто в интернете сижу. Если бы мне кто-нибудь предложил скачать 5 метров просто чтобы начать пользоваться программой, то я бы сразу послал такой сервис.
А твой сервис с торможением по минуте на _каждое_ действие пошлют ещё дальше.
G>Короче хватит практиковаться в выдумывании небылиц. Адекватного описания преимуществ твоего подхода не видно, а все что есть вполне делается и без h\orm.
Ну да. Твой подход требует:
1) Большого расхода времени.
2) В 10-100 раз большего количества серверов.
3) Гораздо более сложного программирования — ручного отслеживания зависимостей.
4) Мешанины UDF, SP и прочих "радостей".
5) Зависимость от конкретной БД.
6) Не будет работать на модеме.
...
Зато у него один плюс — не будет использоваться H/ORM. Самому-то не смешно?