Здравствуйте, matumba, Вы писали:
M>заодно слегка так обосрал оппонента
А кто первый начал обсирать? «Хомячки с промытыми мозгами», «ленивые твари». У меня много знакомых, которые как раз описанными делами и занимаются. Корзинами, например. Отличные люди, трудолюбивые, работают по 12 часов в день, и мозги получше некоторых имеют. Кстати, без комплексов и этот бред про промытые мозги они бы прочитали с улыбкой. Близко к сердцу бы не приняли. Но они это они, а мне чего переживать о самолюбии человека, который за своим обсирательным аппаратом не следит?
Что касается использования, то уже использовал. Спасибо за предоставление портрета.
Здравствуйте, Ikemefula, Вы писали:
I>Это зависит от топологии, можно наверное 10-20 взять, я так навскидку не могу сказать, потому что уже ен работаю на этом проекте.
Ок, получаем десяток мегбайт на всё. Нафиг тут выборки? Тут клиент в айфоне будет летать.
I>Ну ты же понимаешь, что приложение решает не одну эту задачу, потому данных намного больше. Один кусочек вполне может влезть в L1, но сначала надо сделать выборку. Может даже 100 байт хватит,но каким способом быстро выяснить, какие именно 100 байт тебе надо ?
Пойти по указателю
I>Для одной задачи может и 100 байт быть. Но ведь приложение не решает одну единственную задачу. У линка например есть куча всяких свойств, ИД внезапно становится GUID, есть поля DateTime, есть всякие каналы, сегменты, парселы и тд и тд и тд и тд.
Ну и что.
I>Вот обеспечить эту локальность очень трудно. Например ты захочешь удалить или изменить свойства узла. Внезапно оказывается, надо поудалять целую кучу приконнекченых к нему объектов.
Ну и что? "Целая куча" — это около сотни объектов. Какова частота внесения изменений? Судя по описанию, тут для транзакционности достаточно глобального лока на всю систему, т.к. время модификации невелико. I>Например узел может присоединять только линки определенных типов. Меняешь тип узла, опаньки, все левые линки должны быть удалены, а до этого весь роутинг и тд и тд.
С учётом того, что полный список "приконнекченных" к узлу линков хранится в готовом виде, ничего военного получении списка нет. I>отдельный случай, топология все на всех — каждый узел связан со всеми остальными узлами. Как тут обеспечить локальность изменений, не ясно.
В этом случае с локальностью всё плохо. I>Это понятно. Мне не понятно, какие еще данные тебе нужны.
Для полного решения нужен точный список сценариев, которые нужно обеспечить, с частотами выполнения, степенью конкурентности и прочим.
Набросок я уже предоставил. Пока что получается так, что всё вполне можно хранить на сервере в RDBMS, потому что требований к производительности там считай что нет.
Весь адский перформанс достигается на клиенте, который загружает всю базу целиком в память, а изменения реплицируются по несложному протоколу.
I>Получить у узла весь генерируемый трафик, нужно по узлу получить все его линки, по каждому линку получить пути, каждого пути получить линки и все начинается заново и так до самого низа.
Совершенно непонятно, что мешает всю эту радость сделать на клиенте чисто в памяти. Благо объёмы, о которых идёт речь, сейчас ставят в наручные часы. Я бы понял, если бы у вас сеть весила десяток гигабайт. Вот тогда бы имело смысл заморачиваться вытеснением на диск или в сервер и вопросами оптимизации "запросов", чтобы ограничивать трафик между медленной и быстрой памятью. I>Или такая вещь — обновить длину логических линков в соответствии с роутингом на физическом уровне. Надо раскрутить весь роутинг и пересчитать длину начиная с конца.
Ну, как мы уже выясняли, это не нужно делать за 100мс. Поэтому особых проблем я не вижу.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>Это зависит от топологии, можно наверное 10-20 взять, я так навскидку не могу сказать, потому что уже ен работаю на этом проекте. S>Ок, получаем десяток мегбайт на всё. Нафиг тут выборки? Тут клиент в айфоне будет летать.
Выборки нужны по той причине что полная модель это десятки миллионов экземпляров. Скажем для дотнета это автоматически съедает около 100-200 мб если считать по восемь байт на объект
I>>Для одной задачи может и 100 байт быть. Но ведь приложение не решает одну единственную задачу. У линка например есть куча всяких свойств, ИД внезапно становится GUID, есть поля DateTime, есть всякие каналы, сегменты, парселы и тд и тд и тд и тд. S>Ну и что.
Всего десяток другой джойнов для выборки роутинга для одного слоя
I>>Вот обеспечить эту локальность очень трудно. Например ты захочешь удалить или изменить свойства узла. Внезапно оказывается, надо поудалять целую кучу приконнекченых к нему объектов. S>Ну и что? "Целая куча" — это около сотни объектов. Какова частота внесения изменений? Судя по описанию, тут для транзакционности достаточно глобального лока на всю систему, т.к. время модификации невелико.
Модификация это отдельный сценарий, его лучше не касаться. Отдельные сценарии модификации занимают минуты.
I>>Например узел может присоединять только линки определенных типов. Меняешь тип узла, опаньки, все левые линки должны быть удалены, а до этого весь роутинг и тд и тд. S>С учётом того, что полный список "приконнекченных" к узлу линков хранится в готовом виде, ничего военного получении списка нет.
А джойны куда девать? А передачу по сети? Ну предположим sql запрос будет ноль времени. На каждый клик нужно по три-десять мб гонять на клиент. Чтобы успеть за секунду это нужно 30-100 мегабит канал по самой скромной оценке. А если сервер будет пользовать десяток людей то уже оказывается что гигабита не хватит. Кастомеру нужны тысячи и десятки тысяч пользователей. Фокус в том что sql решение дохнет уже на одном. Потому возможности серверного совсем отличные от стандалона — много данных и пользователей но слабая визуализация
I>>отдельный случай, топология все на всех — каждый узел связан со всеми остальными узлами. Как тут обеспечить локальность изменений, не ясно. S>В этом случае с локальностью всё плохо.
Хуже некуда потому грузили все в память
I>>Это понятно. Мне не понятно, какие еще данные тебе нужны. S>Для полного решения нужен точный список сценариев, которые нужно обеспечить, с частотами выполнения, степенью конкурентности и прочим.
Ты же хотел упрощенную задачу а тут уже спецификация на приложение нужна
S>Набросок я уже предоставил. Пока что получается так, что всё вполне можно хранить на сервере в RDBMS, потому что требований к производительности там считай что нет. S>Весь адский перформанс достигается на клиенте, который загружает всю базу целиком в память, а изменения реплицируются по несложному протоколу.
1-2 гигабайта в памяти если грузить все. Реально нужны обьемы примерно на порядок больше. Неясно как тут добиться быстрого отклика.
I>>Получить у узла весь генерируемый трафик, нужно по узлу получить все его линки, по каждому линку получить пути, каждого пути получить линки и все начинается заново и так до самого низа. S>Совершенно непонятно, что мешает всю эту радость сделать на клиенте чисто в памяти. Благо объёмы, о которых идёт речь, сейчас ставят в наручные часы. Я бы понял, если бы у вас сеть весила десяток гигабайт. Вот тогда бы имело смысл заморачиваться вытеснением на диск или в сервер и вопросами оптимизации "запросов", чтобы ограничивать трафик между медленной и быстрой памятью.
Сделали в памяти гдето десять лет наЗад и на sql это слабо похоже
I>>Или такая вещь — обновить длину логических линков в соответствии с роутингом на физическом уровне. Надо раскрутить весь роутинг и пересчитать длину начиная с конца. S>Ну, как мы уже выясняли, это не нужно делать за 100мс. Поэтому особых проблем я не вижу.
Здравствуйте, Ikemefula, Вы писали:
I>Выборки нужны по той причине что полная модель это десятки миллионов экземпляров. Скажем для дотнета это автоматически съедает около 100-200 мб если считать по восемь байт на объект
С учётом того, что на моём ноуте 8GB оперативки, по прежнему не вижу проблемы держать в памяти 200 мегабайт.
I>Всего десяток другой джойнов для выборки роутинга для одного слоя
Это если нестерпимо хочется заниматься джойнами на лету, вместо того, чтобы предрассчитать результаты.
I>Модификация это отдельный сценарий, его лучше не касаться. Отдельные сценарии модификации занимают минуты.
Тогда вообще никаких проблем нет I>А джойны куда девать?
Какие ещё джойны? Я же вам нарисовал схему. В ней нет никаких джойнов. I>На каждый клик нужно по три-десять мб гонять на клиент. Чтобы успеть за секунду это нужно 30-100 мегабит канал по самой скромной оценке.
Зачем? К моменту клика всё уже на клиенте. Эти жалкие 200 мегабайт не стоят того, чтобы бегать за ними на сервер каждую секунду. I>А если сервер будет пользовать десяток людей то уже оказывается что гигабита не хватит. Кастомеру нужны тысячи и десятки тысяч пользователей. Фокус в том что sql решение дохнет уже на одном. Потому возможности серверного совсем отличные от стандалона — много данных и пользователей но слабая визуализация
Ничего не понимаю. Вы явно имеете в виду какое-то кривое решение достаточно простой задачи.
I>1-2 гигабайта в памяти если грузить все. Реально нужны обьемы примерно на порядок больше. Неясно как тут добиться быстрого отклика.
Откуда внезапно появились гигабайты? Начали мы со ста тысяч объектов, а теперь вы на лету меняете задачу.
I>Сделали в памяти гдето десять лет наЗад и на sql это слабо похоже
У вас тут нет задачи для SQL.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>Выборки нужны по той причине что полная модель это десятки миллионов экземпляров. Скажем для дотнета это автоматически съедает около 100-200 мб если считать по восемь байт на объект S>С учётом того, что на моём ноуте 8GB оперативки, по прежнему не вижу проблемы держать в памяти 200 мегабайт.
Объект в дотнете, если 32 бита система, занимает минимум 8 байт. десять миллионов экземпляров займут 80 мб и это вообще ничего — ни единой ссылки, ни единого свойства.
В 32х битной системе в принципе невозможно держать большую модель в памяти, там ровно один гб для дотнета, +-100-200мб на фрагментацию.
Быстрая визуализация требует больших ресурсов, кроме того, операционную систему пока еще никто не отменял. Твои 8гб это _копейки_.
Вль например далеко не самая большая сеть, в памяти занимает 30млн экземпляров. Это уже 240мб на одни только заголовки объектов.
S>Какие ещё джойны? Я же вам нарисовал схему. В ней нет никаких джойнов.
Ты лучше покажи, как ты предлагаешь хранить линки, слои, пути и тд. Как все это можно слить в одну структуру для конкретной операции объяснять не надо, это сделано 10 лет назад.
Потом покажи конкретный запрос, который сформирует эту структуру.
I>>1-2 гигабайта в памяти если грузить все. Реально нужны обьемы примерно на порядок больше. Неясно как тут добиться быстрого отклика. S>Откуда внезапно появились гигабайты? Начали мы со ста тысяч объектов, а теперь вы на лету меняете задачу.
Если говорить ровно про одну задачу, как про коня в вакууме, то ты сам убедился, что SQL не нужен.
Если говорить про один сценарий из приложения, то надо понимать, что модель намного больше чем конкретные данные для конкретной операции, минимум на два порядка.
На клиенте это уже не получается держать, а SQL решение сосёт не нагибаясь из за джойнов.
Скажем если все держать на клиенте, не совсем понятно, как будет многопользовательский доступ реализован. А если скачивать на каждый чих часть модели, то получается бедствие.
Здравствуйте, Ikemefula, Вы писали:
I>Объект в дотнете, если 32 бита система, занимает минимум 8 байт. десять миллионов экземпляров займут 80 мб и это вообще ничего — ни единой ссылки, ни единого свойства.
Это пока что рассуждения ни о чём. Потому, что совершенно не факт, что каждый элемент будет заслуживать отдельного объекта. Может быть, обойдемся структурами в массивах.
И ещё раз напомню, что задача ставилась про 100k объектов. Это в 100 раз меньше, чем новая задача.
I>Быстрая визуализация требует больших ресурсов, кроме того, операционную систему пока еще никто не отменял. Твои 8гб это _копейки_.
Это ваши 100к объектов — копейки. А 8гб пока особо и занять-то нечем. I>Вль например далеко не самая большая сеть, в памяти занимает 30млн экземпляров. Это уже 240мб на одни только заголовки объектов.
В памяти или в постановке задачи? А то я и для теоремы Пифагора 30 миллионов "экземпляров" напложу. I>Ты лучше покажи, как ты предлагаешь хранить линки, слои, пути и тд.
Я уже показал, как я их предлагаю хранить. Номера слоя нет, потому что его легко тривиально добавить. I>Потом покажи конкретный запрос, который сформирует эту структуру.
Я вижу, что-то в моём решении вам непонятно. Вы спросите, я отвечу. I>Если говорить ровно про одну задачу, как про коня в вакууме, то ты сам убедился, что SQL не нужен.
SQL нужен там, где есть одновременная многопользовательская работа над структурированными данными.
Вы начали с того, что предложили игнорировать модификации. Это сразу оставляет SQL за бортом. Потом оказалось, что данные для визуализации удобнее хранить кэшированными на клиенте, т.к. задача — квазистатическая; на сотни визуализаций приходятся единицы модификаций. Это позволяет нам иметь комфортную SQL-структуру на сервере и что угодно на клиенте. I>На клиенте это уже не получается держать, а SQL решение сосёт не нагибаясь из за джойнов.
Из-за джойнов... Какая прелесть.
I>Скажем если все держать на клиенте, не совсем понятно, как будет многопользовательский доступ реализован.
Я же вам объяснил — вся многопользовательскость реализуется как два пальца. Клиент заливает изменения на сервер в транзакции, эти изменения неторопливо реплицируются всем остальным клиентам. Поскольку модификации — штука редкая, всё будет работать на ура.
Точно такую же схему использует, скажем, Outlook. Формат локальной базы данных — совершенно другой, чем на сервере.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>Быстрая визуализация требует больших ресурсов, кроме того, операционную систему пока еще никто не отменял. Твои 8гб это _копейки_. S>Это ваши 100к объектов — копейки. А 8гб пока особо и занять-то нечем.
Эдак окажется что любую упрощенную задачу можно ужать в 8гб
I>>Если говорить ровно про одну задачу, как про коня в вакууме, то ты сам убедился, что SQL не нужен. S>SQL нужен там, где есть одновременная многопользовательская работа над структурированными данными.
А вот мне в очередной раз кажется, что упрощенную задачу в отрыве от приложения рассматривать смысла нет, потому что решение будет оптимизировано именно под эти требования, то есть, вообще разговор ни о чем.
I>>Скажем если все держать на клиенте, не совсем понятно, как будет многопользовательский доступ реализован. S>Я же вам объяснил — вся многопользовательскость реализуется как два пальца. Клиент заливает изменения на сервер в транзакции, эти изменения неторопливо реплицируются всем остальным клиентам. Поскольку модификации — штука редкая, всё будет работать на ура.
То есть, в упрощенную задачу надо добавить вообще все сценарии и что бы частота использования была адекватная ?
Здравствуйте, Ikemefula, Вы писали:
I>Эдак окажется что любую упрощенную задачу можно ужать в 8гб
Практически да. Это же то, чего мы хотели — мощность вчерашних мейнфреймов у пользователя на столе.
I>А вот мне в очередной раз кажется, что упрощенную задачу в отрыве от приложения рассматривать смысла нет, потому что решение будет оптимизировано именно под эти требования, то есть, вообще разговор ни о чем.
Тогда сформулируйте ту задачу, которую вы хотите решить.
I>То есть, в упрощенную задачу надо добавить вообще все сценарии и что бы частота использования была адекватная ?
Конечно. Вы странный — сами же сформулировали задачу, а теперь обижаетесь, что у неё есть решение.
Если у вас есть какая-то другая задача, то не стесняйтесь — изложите её. Но учтите, что если вы будете выкидывать "несущественные подробности", то решение опять может вас не устроить.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>А вот мне в очередной раз кажется, что упрощенную задачу в отрыве от приложения рассматривать смысла нет, потому что решение будет оптимизировано именно под эти требования, то есть, вообще разговор ни о чем. S>Тогда сформулируйте ту задачу, которую вы хотите решить.
Та же самая задача, только данных столько что не вместится в твои 8гб + многопользовательский доступ, в частности, через веб-интерфейс. Можешь просто помножить количество данных, что я сообщил, на некоторый коэффициэнт. Идейка та же — по объекту верхнего уровня получить его роутинг на самом нижнем.
Здравствуйте, Ikemefula, Вы писали:
I>Та же самая задача, только данных столько что не вместится в твои 8гб + многопользовательский доступ, в частности, через веб-интерфейс.
Тут тебе таки надо определиться с реальными параметрами. Потому, что в 8 Гб не поместиться можно очень многими способами
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Ikemefula, Вы писали:
I>Та же самая задача, только данных столько что не вместится в твои 8гб + многопользовательский доступ, в частности, через веб-интерфейс. Можешь просто помножить количество данных, что я сообщил, на некоторый коэффициэнт. Идейка та же — по объекту верхнего уровня получить его роутинг на самом нижнем.
Опять фигня какая-то. Вы пытаетесь поставить performance-bound problem, но избегаете говорить о характеристиках производительности.
Данных — неизвестно сколько. Распределение длин роутов — неизвестно. Количество слоёв — неизвестно. Частота изменений — неизвестна. Типы изменений — неизвестны.
Представьте себе, что я предлагаю вам решить задачу умножения матриц. При этом я утверждаю, что ваше решение не подходит по производительности, но ни размеров матриц, ни количества множителей, ни того, насколько часто перемножаются одни и те же неизменные матрицы, я вам сказать не могу.
Зайдём с другого конца. Допустим, мы считаем полное кэширование на клиенте заведомо непрактичным.
То есть, мы строим клиент-серверный протокол взаимодействия: клиент задаёт вопрос, сервер отвечает.
Попробуем оценить, во что нам это обойдётся, хотя бы с точки зрения транспорта.
Если слоёв — 15, и на каждом уровне у нас характерная длина роута — 10, то транзитивное замыкание для одного линка будет затрагивать 10^15 линков.
Это явно какая-то чушь, т.к. столько линков нет даже в самой смелой вашей фантазии. Вы упоминали, что полный путь — "сотни, а может даже и тысячи" линков.
Давайте для определённости предположим, что заказчик хочет живенькой реакции для 10000 связанных линков.
То есть, в ответе мы передаём 10000 * (4 байта ID, 1 байт цвет) = 50 килобайт. Это я уже предполагаю, что все линки в окне просмотра были перед этим запрошены с сервера, и нам не нужно передавать все статические свойства типа координат узлов.
Время передачи у нас = 2 * Latency + Size/Bandwidth, должно быть <= MaxResponse = 1000мс (не будем ставить себе заведомо неразрешимую задачу получить 0.1сек, обеспечивающие идеальную гладкость UI).
Решая неравенство, получаем Bandwidth >= Size/(MaxResponse — 2 * Latency).
Типичная латентность для национального уровня — 50мс, для международного — 250мс. Итого, Bandwidth у нас должен быть не меньше 50kb/0.9c, если всё в пределах одной страны, или 550 килобит. Ок, базовый sanity check мы прошли, можно заниматься проектированием серверной стороны.
Надо понимать, что если условия изменятся, и нам придётся пропихивать не 50 килобайт, а 1 мегабайт за ту же секунду, то проблемы будут не на стороне сервера, а при обеспечении канала.
На сегодня всё, а в следующей серии мы попробуем разобраться, что нужно сделать на серверной стороне, чтобы успеть подготовить список из 10к раскрашенных линков за 900мс
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>Та же самая задача, только данных столько что не вместится в твои 8гб + многопользовательский доступ, в частности, через веб-интерфейс. Можешь просто помножить количество данных, что я сообщил, на некоторый коэффициэнт. Идейка та же — по объекту верхнего уровня получить его роутинг на самом нижнем. S>Опять фигня какая-то. Вы пытаетесь поставить performance-bound problem, но избегаете говорить о характеристиках производительности. S>Данных — неизвестно сколько. Распределение длин роутов — неизвестно. Количество слоёв — неизвестно. Частота изменений — неизвестна. Типы изменений — неизвестны.
Да вроде как по данным все известно На счет длин роутов я даже и не могу сказать, это сильно зависит от топологии и алгоритмов/параметров роутинга. Есть роуты скажем для Слоев обычно 10-20. Про изменения пока не нужно ничего делать.
S>Время передачи у нас = 2 * Latency + Size/Bandwidth, должно быть <= MaxResponse = 1000мс (не будем ставить себе заведомо неразрешимую задачу получить 0.1сек, обеспечивающие идеальную гладкость UI). S>Решая неравенство, получаем Bandwidth >= Size/(MaxResponse — 2 * Latency). S>Типичная латентность для национального уровня — 50мс, для международного — 250мс. Итого, Bandwidth у нас должен быть не меньше 50kb/0.9c, если всё в пределах одной страны, или 550 килобит. Ок, базовый sanity check мы прошли, можно заниматься проектированием серверной стороны. S>Надо понимать, что если условия изменятся, и нам придётся пропихивать не 50 килобайт, а 1 мегабайт за ту же секунду, то проблемы будут не на стороне сервера, а при обеспечении канала.
S>На сегодня всё, а в следующей серии мы попробуем разобраться, что нужно сделать на серверной стороне, чтобы успеть подготовить список из 10к раскрашенных линков за 900мс
Собтсвенно это самое интересное. Хотелось бы увидеть как ты будешь хранить всю сеть и как будешь делать на ней запросы вроде тех, что я показал.
Здравствуйте, Ikemefula, Вы писали: S>>На сегодня всё, а в следующей серии мы попробуем разобраться, что нужно сделать на серверной стороне, чтобы успеть подготовить список из 10к раскрашенных линков за 900мс I>Собтсвенно это самое интересное. Хотелось бы увидеть как ты будешь хранить всю сеть и как будешь делать на ней запросы вроде тех, что я показал.
Спрашивайте — отвечаем.
Как хранить всю сеть?
По-умолчательный способ безо всяких денормализаций — это хранить табличку "кто через кого роутится":
create table Routes(
sourceLink int not null foreign key references Link(id),
targetLink int not null foreign key references Link(id),
isPrimaryRoute tinyint not null,
constraint RoutePK primary key clustered(sourceLink, targetLink, isPrimaryRoute)
)
Как делать к ней запросы?
Очень просто, ANSI SQL поддерживает синтаксис Common Table Expressions, на основе которого легко вычислять транзитивные замыкания на графах.
with AllRoutes(sourceLink, targetLink, isPrimaryRoute) as
( select sourceLink, targetLink, isPrimaryRoute from Routes where sourceLink = @linkID
union all
select r.sourceLink, r.targetLink, ar.isPrimaryRoute
from AllRoutes ar inner join Routes r on ar.targetLink = r.sourceLink
)
select targetLink, min(isPrimaryRoute)+2*max(isPrimaryRoute) as ColorId from AllRoutes group by targetLink
Здесь цвета определены элементарно:
0: линк входит только в резервные роуты
1, 2: линк входит и в те, и другие
3: линк входит только в основные роуты
Ой, но это же медленно!
Вот простой T-SQL код который каждый может запустить на MS SQL Server типа 2005 или новее:
set statistics time off
set nocount on
create database GraphTest;
go
use GraphTest
go
create table Node (
id int identity not null primary key clustered,
x int not null default(100),
y int not null default(100)
)
go
create table Link (
id int identity not null primary key clustered,
sourceNode int not null foreign key references Node(id),
targetNode int not null foreign key references Node(id),
layerNumber int not null default 0)
go
create table Routes(
sourceLink int not null foreign key references Link(id),
targetLink int not null foreign key references Link(id),
isPrimaryRoute bit not null,
constraint RoutePK primary key clustered(sourceLink, targetLink, isPrimaryRoute)
)
go
create function CalcRoute(@linkID int) returns table
as return
(
with AllRoutes(sourceLink, targetLink, isPrimaryRoute) as
( select sourceLink, targetLink, isPrimaryRoute from Routes where sourceLink = @linkID
union all
select r.sourceLink, r.targetLink, ar.isPrimaryRoute
from AllRoutes ar inner join Routes r on ar.targetLink = r.sourceLink
)
select * from AllRoutes
)
go
declare @i int
set @i = 0
while (@i<300)
begin
insert into Node default values
set @i = @i + 1
end
insert into Link(sourceNode, targetNode)
select sourceNode.id, targetNode.id from Node as sourceNode, Node as targetNode
select count(*) as totalLinks from Link
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 10 1 as sourceLink, id, 1 from Link where id>1 order by id; -- link #1 gets routed through 2-11;insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 100 ceiling(id/10), id, 1 from Link where id>=20 order by id; -- links #2-11 get routed through links #20-29, 30-39, 110-119, etcinsert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 ceiling(id/10), id, 1 from Link where id>=200 order by id; -- links #20-120 get routed through links #200-209, 210-219, ..., 1200-1209insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 1200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 2200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 3200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 4200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 5200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 6200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 7200 order by id
insert into Routes(sourceLink, targetLink, isPrimaryRoute)
select top 1000 id, id+1000, 1 from Link where id >= 8200 order by id
select count(*) as totalRoutes from Routes
checkpoint
dbcc dropcleanbuffers
set statistics time on
select * from CalcRoute(1)
set statistics time off
use master
drop database GraphTest
Вкратце, что делает код:
1. Создаёт новую базу с таблицами Node, Link, Route.
2. Заполняет её данными:
— 300 нод
— все попарно связаны со всеми, так что линков всего 90000 штук
— "роутов", т.е. отношений "линк A роутится через линк B" — 10110, устроенных следующим образом:
-- линк №1 первого слоя роутится через линки 2-11 второго слоя
-- линки второго слоя роутятся через 10 линков третьего слоя каждый
-- линки третьего слоя роутятся через 10 линков четвёртого слоя каждый
-- четвёртый слой и далее роутятся через 1 линк нижележащего слоя каждый
Таким образом, в транзитивное замыкание для первого линка входят вообще все известные роуты. Заметьте, что я взял более-менее невыгодный случай для SQL — ему приходится делать десять итераций, т.к. ветвистость уровней ниже четвёртого искусственно ограничена. Если бы я сделал по 10 линков на каждом уровне, то мы бы остановились на уровне 4.
Исходные данные упрощены — введены только primary роуты, резервные роуты не подсчитаны.
3. Затем код сбрасывает буфера (чтобы минимизировать эффект от кэширования) и выполняет поиск всех линков, через которых роутится линк #1, измеряя затраченное время.
На моём ноутбуке, в режиме работы от батарейки, я наблюдаю следующий результат:
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
SQL Server Execution Times:
CPU time = 140 ms, elapsed time = 249 ms.
Какие ещё сомнения в дееспособности SQL вы хотите, чтобы я развеял?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Какие ещё сомнения в дееспособности SQL вы хотите, чтобы я развеял?
Мои пожалуйста. Мне почему-то кажется, что основной недостаток RDBMS, это накладные расходы на ACID. То есть там, где они не особо критичны, их можно просто избежать. К примеру это могут быть всякие социальные сети с миллионами лайков, где валовый объем высок, а точные цифры не особо критичны. Заниматься шардингом RDBMS, где ACID все равно начинает нарушаться, я смысла не вижу.
Здравствуйте, Ziaw, Вы писали:
Z>Мои пожалуйста. Мне почему-то кажется, что основной недостаток RDBMS, это накладные расходы на ACID.
Ну, для любителей есть RDBMS с отключаемым ACID — например MySQL.
Z>То есть там, где они не особо критичны, их можно просто избежать. К примеру это могут быть всякие социальные сети с миллионами лайков, где валовый объем высок, а точные цифры не особо критичны. Заниматься шардингом RDBMS, где ACID все равно начинает нарушаться, я смысла не вижу.
А я вот вижу основную проблему в том, что судя по форумам, у нас прямо все пишут социальные сети с миллионами лайков. А в жизни таких сетей — три с половиной штуки.
В итоге люди на полном серъёзе отбрасывают RDBMS по причинам перформанса в тех случаях, когда перформанса RDBMS хватает с запасом в 1000%.
Вот только что мы обсуждали "задачку на графах", где мой оппонент уверял, что вытащить 10000 связанных узлов из RDBMS за время клика невозможно, даже после привлечения "целой бригады программистов". На практике — SQL укладывается в требования на низкооборотистом винте с запасом в 3 раза. Если мы поставим серверный винт, то запас будет 8 раз. И это — решение, набросанное за 15 минут на коленке, без единой оптимизации производительности.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, Sinclair, Вы писали:
S>>Какие ещё сомнения в дееспособности SQL вы хотите, чтобы я развеял?
Z>Мои пожалуйста. Мне почему-то кажется, что основной недостаток RDBMS, это накладные расходы на ACID. То есть там, где они не особо критичны, их можно просто избежать. К примеру это могут быть всякие социальные сети с миллионами лайков, где валовый объем высок, а точные цифры не особо критичны. Заниматься шардингом RDBMS, где ACID все равно начинает нарушаться, я смысла не вижу.
Во-первых миллионы лайков это для RDBMS простая задача. Даже сотни миллионов. И совершенно без шардинга.
Во-вторых 99,9999% программистов такое не пишут и никогда не будут.
В-третьих влияние ACID на скорость сильно преувеличено, ибо веб-приложение с нормальным кешированием его даже не заметит.
Здравствуйте, Sinclair, Вы писали:
S> Как делать к ней запросы? S>Очень просто, ANSI SQL поддерживает синтаксис Common Table Expressions, на основе которого легко вычислять транзитивные замыкания на графах. S>
S> with AllRoutes(sourceLink, targetLink, isPrimaryRoute) as
S> ( select sourceLink, targetLink, isPrimaryRoute from Routes where sourceLink = @linkID
S> union all
S> select r.sourceLink, r.targetLink, ar.isPrimaryRoute
S> from AllRoutes ar inner join Routes r on ar.targetLink = r.sourceLink
S> )
S> select targetLink, min(isPrimaryRoute)+2*max(isPrimaryRoute) as ColorId from AllRoutes group by targetLink
S>
Я не понял фокус с цветами. Цвет линка на нижнем уровне определяется цветом самого верхнего пути, основной, резервный или смешаный. Шота не пойму как у тебя это получается.
Здравствуйте, Sinclair, Вы писали:
S>На моём ноутбуке, в режиме работы от батарейки, я наблюдаю следующий результат: S>
S>DBCC execution completed. If DBCC printed error messages, contact your system administrator.
S> SQL Server Execution Times:
S> CPU time = 140 ms, elapsed time = 249 ms.
S>
S>Какие ещё сомнения в дееспособности SQL вы хотите, чтобы я развеял?
В реальной модели роутинг раскручивается через гораздо большее количество сущностей, а именно несколько типов линков, каналы и тд и тд.
например роутинг может быть такой — клиентский линк(на самом верху только такие) имеет ровно один основной путь и несколько резервных, эти пути состоят из коннекшнов на нижний слой. Далее у каждого коннекшна есть путь из сегментов, у каждого сегмента путь из отрезков, каждому отрезку соответсвует канал в каждом из путей состоящем из простых линков. У каждого простого линка есть клиентский линк, это самый низ роутинга в слое, те здесь слой заканчивается и дальше повторяется как описано — коннекшны, сегменты, отрезки, каналы и простые линки и тд до самого низа. На самом низу клиентских уже нет.
Коннекшны, сегменты, отрезки — все пути из этих объектов могут быть как основными так и резервными.
И напоследок — клиентские линки могут быть вложеными. То есть, один клиентский линк содержит в себе несколько других клиентских,всегда два уровня. Вложенный роутится или сам или же его дочерние клиентские линки.
На самом верху только клиентские, на самом низу только все остальные.
Вся эта кухня нужна для получения например устойчивости сети к сбоям и тд и тд.
Вопрос — во сколько оценишь время работы аналогичного запроса, если скажем количество простых линков в пути будет примерно таким же, как ты посчитал в уже решенной задаче ?
Здравствуйте, Sinclair, Вы писали:
S>Вот только что мы обсуждали "задачку на графах", где мой оппонент уверял, что вытащить 10000 связанных узлов из RDBMS за время клика невозможно, даже после привлечения "целой бригады программистов".
Это ж была упрощенная задача. Теперь хочется смасштабировать подход на реальную модель и получить хотя бы оценки сверху-снизу. Собственно я говорю про факты которые довелось наблюдать, а саму серверную базу я не проектировал и даже запросов по ней не гонял, чисто замеры перформанса аналогичного функционала.
Здравствуйте, gandjustas, Вы писали:
G>В-третьих влияние ACID на скорость сильно преувеличено, ибо веб-приложение с нормальным кешированием его даже не заметит.
Q: Где взять сильного dba ?
A: Из таблицы сильных dba выбрать первого.