Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Где лучше выполнять арифметические операции? На клиенте или на сервере? (https://javascript.ru/forum/misc/27663-gde-luchshe-vypolnyat-arifmeticheskie-operacii-na-kliente-ili-na-servere.html)

Маэстро 24.04.2012 11:31

DjDiablo, trikadin,
понимаете... только без обид, ладно? Но вы мыслите устаревшими категориями.
Что пейджинг c фильтрами уже не моден?
Типа уже не моден. Точнее, исчерпал себя. Точнее, никто ничего не предлагает другого. Есть альтернатива? - Да.

Теперь круто получить HTML'ку этак высотой в 80 экранов ?
Да, круто. Но это не те 80 экранов, которые выльются в 80 мегабайт трафика. Есть другая технология.

Комп стандартной мощности верстать таблицу > 10000 ячеек будет долго.
Бесспорно. А 10000 строк? - умрёт вообще. Однако, есть другая технология... ;)

Существуют задачи (в частности у предприятия, которое я автоматизирую), в которых менеджеры желают бегло просматривать по 1000-3000 записей из базы данных. Бегло - это значит быстро, не тратя даже пол-секунды на лишние действия. Поэтому стандартный страничный пейджинг уже раздражает. Также раздражает DOM-массив элементов, лежащий в памяти, который изображает из себя таблицу, построенную на html-теге <table>. Если таблица имеет всего 1000 строк х 100 столбцов, то она становится неповоротливой, а в IE почти недвижимой. Раздражает.
Такого рода задачи присутствуют в бизнесе под названием логистика, грузооборот, товарооборот. В этих случаях менеджер хочет видеть как суммарные показатели, так и оперативную информацию по каждой позиции детально и всё одновременно.
А теперь об альтернативе. Изучив потребности пользователей, я предложил и разработал технологию построения больших таблиц вообще без использования <table>. Если коротко, то суть в том, что моя таблица - это как бы вьюпорт, который ползает по виртуальным "80 экранам" и аджаксом динамически подкачивает с сервера информацию в зависимости от положения скроллера и других управляющих воздействий пользователя.
В общем-то я уже об этом писал здесь: http://javascript.ru/forum/project/2...-kontakty.html
Пример, который могу показать, здесь: http://gigalit.info

DjDiablo 24.04.2012 13:40

Да мы вроде не интерфейс обсуждаем.

Речь шла о том что инфу хорошо бы разбить на блоки,
при использовании подгрузки по ajax ты это как раз и делаешь.

Маэстро 24.04.2012 13:51

Цитата:

Сообщение от DjDiablo (Сообщение 170927)
Речь шла о том что инфу хорошо бы разбить на блоки, при использовании подгрузки по ajax ты это как раз и делаешь.

Да, именно так. Но вот теперь вопрос к тем, кто склоняется к варианту все вычисления "свалить на клиента": при динамической подгрузке таблицы блоками мы в общем случае не имеем на клиенте ВСЕЙ таблицы, имеем только часть её. Поэтому оперативные показатели (например, количество товара, умноженное на цену товара) можем посчитать по строке. Но мы не можем посчитать сумму всех показателей по одному столбцу таблицы (т.к. она на клиенте может быть до конца не заполнена). Я прихожу к выводу, что такую сумму можно посчитать только на сервере и прислать либо вместе с ответом на блоковый ajax-запрос, либо оформить отдельным запросом.

trikadin 24.04.2012 14:36

Маэстро, знаете, обсуждение потихоньку приходит к виду "А я вам докажу, что на сервере лучше!"

Необязательно доказывать, правда)

Изначально вы писали:
Цитата:

Сообщение от Маэстро
Задачка такая: надо отобразить таблицу из трех колонок и тысячи строк. В первом столбце - число А, во втором - число B, в третьем - С, где C = A+B.

Для этой задачи, как считаю я и остальные форумчане, лучше всего использовать клиент. Но теперь выясняется, что нужно ещё и сумму всех строк выводить.

Так что предлагаю определиться, какова в итоге задача, и, исходя из этого, искать продуктивное решение.

Кстати, о сумме всей таблицы - я бы на вашем месте завёл отдельное поле в базе данных, в котором бы хранил это значение - чтобы каждый раз не считать.

Маэстро 24.04.2012 14:52

Цитата:

Сообщение от trikadin (Сообщение 170940)
Маэстро, знаете, обсуждение потихоньку приходит к виду "А я вам докажу, что на сервере лучше!"

Согласен. Но доказать я хочу это не Вам, а самому себе. И поверьте, тоже хочу производить все вычисления на клиенте (по разным причинам). А на сервере не "лучше", а... типа от безысходности.

Цитата:

Сообщение от trikadin (Сообщение 170940)
Так что предлагаю определиться, какова в итоге задача, и, исходя из этого, искать продуктивное решение.

Да, я открыл тему простой задачей, но по ходу описал примеры других задач и уже раза два написал, что мой первоначальный вопрос трансформировался в несколько другой: о критерии разделения задач на исполняемые на сервере и исполняемые на клиенте.

Цитата:

Сообщение от trikadin (Сообщение 170940)
Кстати, о сумме всей таблицы - я бы на вашем месте завёл отдельное поле в базе данных, в котором бы хранил это значение - чтобы каждый раз не считать.

Категорически против. Тогда на операцию update/insert/delete любого поля таблицы надо вешать триггер, который сразу будет запускать механизм пересчета всей суммы таблицы чтобы сохранить её новое значение в "отдельном" поле. Представляете как грузанем сервер базы данных? Во вторых, при вызове пользователем таблицы включаются фильтры данных, например, по отделам товаров, по компаниям-производителям, по длине диагонали (для телевизоров) и т.д. Поэтому невозможно на все случаи жизни (случаи фильтрации данных) заложить отдельные ячейки для хранения сумм.

dmitriymar 24.04.2012 15:18

Цитата:

Сообщение от trikadin
Можно пример?

тригонометрические операции.
расчёт трансформаций .
расчёты для граф. вывода информации в 3д.
цепочки расчётов
................................

DjDiablo 24.04.2012 15:33

Раз уж зашёл разговор о местах где можно выполнить расчёты, то я добавлю.
есть как минимум 5 способов,посчитать сумму всех строк

1) посчитать всё при отдаче данных с сервера
2) Посчитать на клиенте, передав туда все данные.
3) Посчитать сумму всех строк при добавлении записи в бд, и сохранить результат куда нубудь. (то что преложил Trikadin)
4) Прокешировать результат суммы строк. То есть, когда сервер возвращает данные он возвращает их из кеша, но если в бд произошли изменения то он считает сумму строк, записывает их в кеш и только потом возвращает результат. Определять необходимость перерасчёта суммы, можно по двум временным меткам. Одна метка, это время последней операции записи, вторая эта время (последней операции записи) которая участвовала в расчёте кеша. Если при операции получения выясняется что время последней операции не совпадает со (временем операции записи) участвующей в последнем расчёте кеша, значит кеш нужнается в перерасчёте.

5) Перманентный расчёт суммы строк. (в 1С эту функцию исполняют регистры) Этот подход проще описать алгоритмом. Допустим нам нужна стоимость всех товаров на складе.
У нас есть уже посчитанная в кеше сумма всех товаров, нам необходимо изменить количество памперсов на складе.
а) стоимость товаров на складе =стоимость товаров на складе-количество памперсов *на стоимость памперсов.
б) Записываем в бд новое количество памперсов.
в) Стоимость товаров на складе =стоимость товаров на складе+количество памперсов *на стоимость памперсов.

Тоесть я просто отнял старую стоимость всех памперсов а потом прибавил новую. Это гораздо быстрее чем из за пары памперсов суммировать все строки в базе (десятки тысяч).

Если подытожить, то максимальное быстродействие обеспечат именно регистры, такие же как в системе 1С. Причём при помощи регистров можно реализовать 99% всех типов расчётов (даже такие как прогноз продаж в следующем периоде). Добавлю что изменение записи в таблице товаров и регистре лучше обьединить в одну транзакцию. нелишним будет и создание утилиты обслуживания, которая используется в случае повреждения бд/ручного вмешательства в бд. Суть работы такой утилиты сводится к перерасчёту всех регистров на основании бд, аналогичный инструмент есть и в 1с.

trikadin 24.04.2012 15:40

Цитата:

Сообщение от dmitriymar
тригонометрические операции.
расчёт трансформаций .
расчёты для граф. вывода информации в 3д.
цепочки расчётов

А почему, собственно? Ведь точности (пусть и относительной) при вычислении таких вещей удаётся добиться и в php, и в C++, и в других языках... Почему не получится в js?)

Цитата:

Сообщение от DjDiablo
Если при операции получения выясняется что время последней операции не совпадает

Маленькое уточнение: если время последнего расчёта позднее последнего обновления кеша.

Они могут не совпадать и просто потому, что вычислились в разные миллисекунды.

Маэстро 24.04.2012 16:48

Цитата:

Сообщение от DjDiablo (Сообщение 170950)
4)Прокешировать результат суммы строк. То есть, когда сервер возвращает данные он возвращает их из кеша, но если в бд произошли изменения то он считает сумму строк, записывает их в кеш и только потом возвращает результат. Определять необходимость перерасчёта суммы, можно по двум временным меткам. Одна метка, это время последней операции записи, вторая эта время (последней операции записи) которая участвовала в расчёте кеша. Если при операции получения выясняется что время последней операции не совпадает со (временем операции записи) участвующей в последнем расчёте кеша, значит кеш нужнается в перерасчёте.

Сколько предполагаете держать суммарных ячеек в кэши? 2-3, или 200-300? Вы предлагаете сравнивать метки времени операции. Но кроме сравнения времен необходимо еще сравнивать какие строки таблицы базы данных участвовали в операции суммирования. Как я уже сказал, применяются фильтры. В одном случае из всей таблицы выбираются только холодильники, во втором только телевизоры. Значит надо сравнивать еще и диапазон значений, который участвовал в операции, так ведь? А как? По ID записей - нельзя. Значит, в худшем случае при любом чихе в БД (update поля "количество товара") придется пересчитывать ВСЕ кеши (200-300). И в чем же мы выиграли?

Цитата:

Сообщение от DjDiablo (Сообщение 170950)
5)Перманентный расчёт суммы строк ...
Тоесть я просто отнял старую стоимость всех памперсов а потом прибавил новую. Это гораздо быстрее чем из за пары памперсов суммировать все строки в базе (десятки тысяч).

Скажу честно на практике этот подход не проверял, но продумывал. И решил не использовать вот по какой причине. Когда Вы изменяете количество памперсов в какой-то одной строке, то всё хорошо. Но бывают групповые операции, типа пользователь выделяет и удаляет 100 строк сразу. К чему это приведет? К тому, что вместо одного SQL-запроса по таблице надо будет сделать 100 операций.

Цитата:

Сообщение от DjDiablo (Сообщение 170950)
Если подытожить, то максимальное быстродействие обеспечат именно регистры, такие же как в системе 1С. Причём при помощи регистров можно реализовать 99% всех типов операций

Мне кажется Вы говорите об однопользователской 1С-ке. У меня запросы клиентов к базе множественные и асинхронные. И через инет. Возможно такое, что первый запрос будет подан раньше второго, а обработан позже второго! И... сплошная каша. И я её боюсь ;)

DjDiablo 24.04.2012 16:49

отвечаю пока на #32 топик
Извиняюсь если непонятно выразился, я уточню что имел ввиду в 4м примере.
$A- время последнего изменения в таблице товаров
$B- время операции основания которая была использована для последного расчёта кэша,
$cashe- это типо кэш.
вреале вся инфа в переменные предварительно загружается из бд, а в конце в бд сохраняется, но мы это опустим
if ($A==$B) echo "Сумма всех товаров: ".$cashe;
else {
   // здесь мы расчитываем новый кэш
   cashe= ...................
  $B= $A;// теперь время последней операции считается временем которое мы использовали для последнего расчёта кеша.
}

Тоесть нам пофиг что было раньше что позже, мы просто сравниваем два значения между собой, и если они отличаются то пересчитываем кэш. Вместо времени можно было и порядковый номер операции использовать.


Часовой пояс GMT +3, время: 23:14.