Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Я когда писал думал переформулировать это место, но решил что достаточно написать "будет стопроцентным" вместо "станет стопроцентным". EP>Ок, переформулирую: После того как каждый запрос был вызван по разу, hit ratio для всех последующих запросов, исключая начальные, будет стопроцентным, то есть каждый следующий запрос попадёт в кэш
Попробуем сформулировать так:
1. У нас есть некий объём исходных (хранимых) данных. Он — хорошо известен; его даже можно достаточно надёжно оценить заранее.
2. У нас есть язык, позволяющий строить производные данные. В простом случае, мы получаем 1:1 соотношение в объёмах — select * from customers.
В более интересных случаях у нас есть потенциальная бесконечность результатов запросов:
select * from customers where name like 'a%'
select * from customers where name like 'b%'
...
select * from customers where name like 'z%'
select * from customers where name like 'aa%'
select * from customers where name like 'ab%'
...
select * from customers where name like 'az%'
...
По мере исполнения этих запросов, страничный кэш будет прогреваться, и hit ratio будет возрастать, потому что объём исходных данных конечен. А вот кэш результатов по прежнему будет показывать hit ratio = 0.
Именно поэтому кэш результатов и непопулярен среди промышленных СУБД.
Приложение может иметь больше данных о том, какие запросы имеют шансы на повторное обращение. Но вместо того, чтобы объяснять СУБД "пожалуйста, закешируй эти данные, чтобы я в следуюший раз получил их быстрее", логичнее закешировать их самому, и не обращаться к СУБД за несвойственной ей обязанностью.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S>>Только на этом сайте есть, емнип, четыре статьи про то, как хранить деревья в SQL.
M>Но лучше не хранить Графовые базы данных рулят
Это новость для меня. А можно ссылку на какой-нибудь dummy guide по какой-нибудь графовой СУБД?
Не обязательно по рулящей — пусть хотя бы не очень сосёт
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, alex_public, Вы писали:
_>Любой подход, который для полного (на всю глубину) обхода поддерева заставляет генерировать рекурсивные запросы к БД, можно сразу выкидывать на помойку.
А можно как-то развернуть и аргументировать это высказывание?
Т.е. привести оценки количества disk access для этого "любого подхода" в сравнении с тем подходом, который вы считаете приемлемым.
А то может я что-то пропустил за 10 лет, истекшие с моего девелоперского прошлого?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
EP>>Я когда писал думал переформулировать это место, но решил что достаточно написать "будет стопроцентным" вместо "станет стопроцентным". EP>>Ок, переформулирую: После того как каждый запрос был вызван по разу, hit ratio для всех последующих запросов, исключая начальные, будет стопроцентным, то есть каждый следующий запрос попадёт в кэш S>Попробуем сформулировать так:
Выше было заявлено что для равновероятных запросов hit-ratio будет нулевым, причём это "очевидно". Я привёл контрпример.
S>Приложение может иметь больше данных о том, какие запросы имеют шансы на повторное обращение. Но вместо того, чтобы объяснять СУБД "пожалуйста, закешируй эти данные, чтобы я в следуюший раз получил их быстрее", логичнее закешировать их самому, и не обращаться к СУБД за несвойственной ей обязанностью.
"Самому" это как? Самому возиться с актуальностью данных? Добавлять зависимость в систему от дополнительных third-party решений?
Где-то может и имеет смысл, но думаю "не всё так однозначно"
Здравствуйте, Sinclair, Вы писали:
S>В рамках одного запроса он непревзойдён — встроенную в него механику вывода типов десятилетиями не удавалось догнать в промышленных языках программирования. S>(Вот я, к примеру, до сих пор не вполне понимаю, каким образом эту проблему решает sqlpp).
Что конкретно? На основе проекции создать соответствующий тип данных?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, Sinclair, Вы писали:
S>>В рамках одного запроса он непревзойдён — встроенную в него механику вывода типов десятилетиями не удавалось догнать в промышленных языках программирования. S>>(Вот я, к примеру, до сих пор не вполне понимаю, каким образом эту проблему решает sqlpp).
EP>Что конкретно? На основе проекции создать соответствующий тип данных?
Да. В С# чтобы решить эту "маленькую частную проблемку, известную под названием Великой проблемы Ауэрса", прикрутили Анонимные Типы и их вывод по использованию в query comprehensions.
Как у нас с этим обстоят дела в С++?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>А что конкретно вас смущает? Есть N способов работать с графами в SQL. можно — через CTE, можно — через транзитивное замыкание. S>В целом, работу с графом обычно инкапсулируют в отдельное место — точно так же, как обход дерева спрятан в коде, возвращающем IEnumerable. S>Так и тут — вызываем GetEmployeesByDepartment(Guid departmentId), получаем IQueryable<Employee>. А то, как там внутри происходит вычисление всех вложенных департаментов — личное дело разработчика. S>Это позволяет нам начинать с какой-нибудь простой схемы хранения дерева — например, с CTE, и оптимизировать её по мере надобности, не ломая остальной код. Только на этом сайте есть, емнип, четыре статьи про то, как хранить деревья в SQL.
Нет там ни одного реального способа. Есть только набор полухаков с трудом эмулирующих нормальную работу. Причём традиционно их там два типа: невменяемо тормозные (через рекурсивные запросы к БД) или просто тормозные с нарушением типизации (через пути в виде строк и т.п.).
Здравствуйте, Sinclair, Вы писали:
S>Это не демагогия, а практический опыт.
Практические опыт чего? ) Работы с кэшированными запросами?)
S>Ресурсы — не бесконечны. Они имеют разную стоимость, в зависимости от того, где мы их пытаемся найти. S>Например, добавить процессоров в машину, на которой работает СУБД — дорого. Потому, что у одной машины есть естественный предел, а переход к кластеру — это до сих пор весьма тяжелое приключение, требующее пересмотра архитектуры. Добавление "ещё одного ядра" может вам запрсто обойтись в полмиллиона долларов. Более того, даже кластерная архитектура — не панацея: с ростом размера кластера объем затрат на синхронизацию начинает расти нелинейно; сейчас нет никаких способов неограниченного наращивания мощности кластеров для OLTP-приложений.
S>Добавить ещё ядро к стейтлесс веб-фарме — почти ничего не стоит. Просто потому, что там нет никаких особенностей. Просто деплоим ещё одну машинку за лоад-балансером — и поехали. Амортизированная стоимость одного ядра — копейки.
S>А мощности клиента вообще достаются нам бесплатно вместе с каждым клиентом.
S>То же самое — с памятью. Вы предлагаете, грубо говоря, тратить на кэш ресурсы по $1000/мегабайт, чтобы не тратить ресурсы по $10/мегабайт. S>Деревья выражений разбираются на дешёвых машинах. Если меня не устроит количество одновременных соединений, то я просто добавлю в кластер ещё одну машину, и получу линейный рост bandwidth.
Перевожу этот поток сознания на нормальный русский язык: "если мне надо будет обрабатывать много одновременных запросов, то я построю кластер и буду добавлять в него машины". Так вот у вменяемых людей (которые следят за накладными расходами) тот же объём запросов будет спокойно обрабатываться на стареньком одиночном сервере. )))
S>Я и говорю — отдадим наш респонс (не обязательно HTML) по HTTP, с хидером expiration:never. Это позволит клиенту вообще не обращаться на сервер при последующих запросах. А для тех, кто всё же пойдёт на сервер, поставим reverse proxy (не обязательно nginx).
А я сказал, что для данной задачу БД вообще не нужна. Так что совершенно непонятно что данный пример делает в данной дискуссии.
Здравствуйте, alex_public, Вы писали:
_>Нет там ни одного реального способа. Есть только набор полухаков с трудом эмулирующих нормальную работу. Причём традиционно их там два типа: невменяемо тормозные (через рекурсивные запросы к БД) или просто тормозные с нарушением типизации (через пути в виде строк и т.п.).
Вижу, в теме вы не разобрались. Приходите, когда разберётесь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Mamut, Вы писали:
M>Ему про Фому, он про мне про Ерему.
ОК, я тебя не понял и думал что мы перешли к обсуждению более интересных вещей.
M>Я ему по то, что никакой у всех баз данных несовместимый функционал, он мне про «PostgreSQL еще не будущее».
M>Я про то, что любое приложение почти сразу начнет использовать функционал, предоставляемый конкретной базой данных, потому что движок сможет предоставить лишь общий для всех баз функционал, он мне про «PostgreSQL еще не будущее».
Какое приложение, какой движок? ) Вот есть у нас скажем какой-нибудь phpbb, который умеет работать считай со всеми реляционными СУБД. Я его просто инсталлирую, подключаю к своей базе (любой) и всё работает. Как эта реальность соотносится с твоими теориями? )
M>Я про то, что даже в тройке лидеров БД (Oracle, MySQL, MS SQL) несовместимый функционал между всеми тремя, и любой движок будет ограничен только общим функционалом, а приложение, даже использующее такой движок, почти сразу начнет завязываться на возможности базы, а он мне про «PostgreSQL еще не будущее».
Ну так этот общий функционал более чем достаточен для большинства целей. Здесь естественно подразумевается именно функционал, а не синтаксис для него (который может быть разный в разных СУБД).
Здравствуйте, alex_public, Вы писали:
_>Перевожу этот поток сознания на нормальный русский язык: "если мне надо будет обрабатывать много одновременных запросов, то я построю кластер и буду добавлять в него машины". Так вот у вменяемых людей (которые следят за накладными расходами) тот же объём запросов будет спокойно обрабатываться на стареньком одиночном сервере. )))
Это смелое заявление, достойное джедая.
_>А я сказал, что для данной задачу БД вообще не нужна. Так что совершенно непонятно что данный пример делает в данной дискуссии.
Ну, если решать изолированную задачу обработать 1 тип запросов по 1 структуре, то да — СУБД будет только мешать.
А если попытаться решить чуть более сложную задачу — где смешиваются несколько типов сценариев, и помимо скорости исполнения 1 типа запросов нам нужны ещё всякие гарантии целостности данных, а также разумная производительность многих типов запросов, то оказывается, что без "базы данных" ничего не выйдет.
Ну вот, например, попробуйте реализовать форумы, аналогичные RSDN.RU, "без БД".
А когда мы используем БД в реальных приложениях типа RSDN.RU, то оказывается, что
— традиционные методы борьбы со сложностью типа хранимых процедур сливают linq вчистую
— накладные расходы на linq в этих приложениях не видны даже в сильный микроскоп
— стоимость поддержки и разработки на "аналогичных" решениях, которые могли бы сэкономить эти копейки, вызывают резонные вопросы.
Заметьте, вы противопоставляете свои теоретические соображения практическому опыту людей, которые работали с высоконагруженными приложениями.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Mamut, Вы писали:
M>Тебе рассказать как банки работают? Ты будешь плакать кровавыми слезами.
M>Раз в день банки заливают друг другу на FTP-сервера файлы в кривых форматах, созданных еще в 60-х. После чего эти файлы пакетно обрабатываются. Более того, у всех есть cut-off time. Если запрос пришел после, скажем 19:00, он будет обработан после 19:00 на следующий день.
M>Редко какой банк может похватстаться хоть каким-то высоким уровнем что разработчиков что системы. И подавляющее большинство из этих 3000 программистов занято постоянным подпиливанием всего этого говна и изобретением все новых костылей, чтобы создавалась видимость «современного динамично развивающегося банка».
M>У нас есть целая команда, которая постоянно пилит парсеры для payment files, которые мы получаем из банков. Пять банков своими криворукими программерами, неспособными допилить свои говно-кобол и говно-ява системы, чтобы они генерировали корректные по формату файлы, загружают команду из пяти человек на полный рабочий день на протяжение уже нескольких лет.
Вообще то если ты посмотришь дискуссию выше, то обнаружишь, что я писал в точности тоже самое. Как раз про низкий уровень внутрикорпоративного программирования и последствий из этого. )
Здравствуйте, Sinclair, Вы писали:
S>В более интересных случаях у нас есть потенциальная бесконечность результатов запросов:
Фокус в том, что на практике число наиболее популярных запросов будет не просто укладываться в число строк, а будет ещё и намного меньше их. Именно из-за этого и работает идея кэширования. Если бы у нас все запросы были абсолютно равновероятны, то тогда естественно никакие кэши не имели бы смысла. Но я так с ходу даже и не вспомню пример системы с таким распределением запросов.
Здравствуйте, alex_public, Вы писали:
_>Где? Ты назвал порядок процентов от времени запроса. А при этом само время запроса может отличаться на несколько порядков.
Может. Причем даже одних и тех же запросов на разном железе и с разной по наполнению БД.
_> Назови порядок величины накладных расходов в секундах и тогда будет более менее предметный разговор.
Накладных расходов на что конкретно? Они там разные. Расход при первом выполнении, когда парсится ЕТ и компилируются мепперы весьма приличный, десятки и сотни миллисекунд. Расход на вычисление хеша ET на среднем железе порядка сотен микросекунд ЕМНИП, расход на меппинг неотличим от полностью рукопашного кода без каких либо абстракций, т.е. скорее отрицательный, чем положительный, так как руками такое обычно никто не выписывает.
Здравствуйте, Sinclair, Вы писали:
S>А можно как-то развернуть и аргументировать это высказывание? S>Т.е. привести оценки количества disk access для этого "любого подхода" в сравнении с тем подходом, который вы считаете приемлемым.
Приемлемым является подход, позволяющий получить все элементы некого поддерева в один запрос к БД. В принципе вариант с текстовыми путями и запросами вида like '/path/%' это позволяет, но я думаю не стоит объяснять в чём заключается кривизна данного полухака. Вo многих nosql БД всё получается в один запрос без всяких хаков, так сказать by design. Ну и насколько я слышал (сам не пользовался) в некоторые реляционные СУБД (например в тот же PostreSQL) добавляли специальные возможности (типы) для более вменяемой реализации подхода с путями. Но во-первых это уже не SQL, так что точно несовместимо ни с чем. А во-вторых даже вариант с нестроковыми путями всё равно уступает нативным графам по удобству. Хотя кое-как уже работать можно, если конечно согласиться на привязку к конкретной СУБД.
Здравствуйте, alex_public, Вы писали:
НС>>Если не подходит реляционная модель, значит не подходит и РСУБД. _>Да, в случае БД это правильный ответ. А что у нас в случае работы с коллекциями? )
С колекциями совсем другой разговор. Там иные особенности. Основная проблема с перформансом связана с конструированием цепочки энумераторов. Если у тебя инициализаций итераторов много, а количество итераций маленькое, то это время становится заметным на общем фоне. В решарпере как раз такой крайний случай — егойная PSI содержит громадное количество узлов, причем почти в каждом таком узле коротенькие списки вложенных узлов, вплоть до индивидуальных лексем.
При этом абсолютные расходы на создание этих итераторов мизерные, единицы микросекунд и менее.
НС>>С точностью до времени выделения памяти и работы конструктора. _>Хм, ну т.е. на практике в C# такое использовать тоже сомнительно.
Почему это? В шарпе есть структуры.
_>>>Ну естественно подразумевается, что и весь остальной доступ к БД реализован через подобные функции. НС>>Ну вот за это, если ты еще не понял, и надо расстреливать. _>Обоснуй. )
Я вроде как обосновал уже
НС>>Возмоно, но на практике никому не нужно. Итого овердизайн в чистом виде. _>Только почему-то весь веб именно так и устроен. )))
Это ложное утверждение.
НС>>Каких движков? О чем ты? _>Ну например большинство веб-движков работают со многими СУБД именно благодаря такому подходу.
Большинство веб-движков написаны не на шарпе и аналогичного линку там нет.
НС>>Чем он удобный? Тем что его на каждый чих править надо? Или тем что классы в возвращаемом результате провоцируют на нарушение инвариантов? _>Как раз удобнее мыслить в рамках объектов приложения
Удобнее мыслить и так и так. А вот перформанс, если мыслить объектами становится чудовищным.
_>, а не таблиц БД. И именно слой абстракции позволяет это делать (работать с объектами не являющимися полным отображением таблиц).
Ответь на простой вопрос — у тея проекция содержит только часть полей User. Ты что возвращать будешь — незаполненный до конца User или специальный одноразовый User42? Проблемы того и другого решения оставляю в качестве домашнего задания.
_>>> и отсутствие никчемных накладных расходов — это ненужная и вредная работа? НС>>Лишний слой это не отсутствие, это наоборот — присутствие. _>ради удобства от правильной архитектуры.
Здравствуйте, Sinclair, Вы писали:
_>>А я сказал, что для данной задачу БД вообще не нужна. Так что совершенно непонятно что данный пример делает в данной дискуссии. S>Ну, если решать изолированную задачу обработать 1 тип запросов по 1 структуре, то да — СУБД будет только мешать. S>А если попытаться решить чуть более сложную задачу — где смешиваются несколько типов сценариев, и помимо скорости исполнения 1 типа запросов нам нужны ещё всякие гарантии целостности данных, а также разумная производительность многих типов запросов, то оказывается, что без "базы данных" ничего не выйдет.
Речь была про вполне конкретный пример, а не про вообще.
S>Ну вот, например, попробуйте реализовать форумы, аналогичные RSDN.RU, "без БД".
И не собираюсь. Форум — это как раз классическая задача под БД. Правда не факт что реляционную. Современные решения на nosql базах легко обходят по скорости старые движки.
S>А когда мы используем БД в реальных приложениях типа RSDN.RU, то оказывается, что S>- традиционные методы борьбы со сложностью типа хранимых процедур сливают linq вчистую
Не использую подобного.
S>- накладные расходы на linq в этих приложениях не видны даже в сильный микроскоп
Ну значит там есть ещё большое поле для оптимизации в других областях. ))) А вот после них можно и к linq приступать (тогда оно уже будет вполне заметно).
S>- стоимость поддержки и разработки на "аналогичных" решениях, которые могли бы сэкономить эти копейки, вызывают резонные вопросы.
Что значит на "аналогичных" решениях? ) Если речь про обсуждаемый тут sqlcpp11, то это естественно не вариант — глупо писать форум на C++. Это инструмент для совсем других целей и нагрузок. А вот если мы например глянем на какой-то современный форумный движок (ну скажем на nodebb), то увидим, что там и функциональности поинтереснее rsdn.ru и отзывчивость повыше. И это не просто без всяких там linq, а даже без sql вообще.
S>Заметьте, вы противопоставляете свои теоретические соображения практическому опыту людей, которые работали с высоконагруженными приложениями.
Хыхы, это rsdn то являются сложным и высоконагруженными приложением? ) Да подобные нагрузки при аналогичной функциональности держат на простеньких серверах древние php движки с mysql базами.
Здравствуйте, alex_public, Вы писали: _>Приемлемым является подход, позволяющий получить все элементы некого поддерева в один запрос к БД.
Как вы ловко перешли от производительности (которая определяется количеством чтений с диска) к "получению одним запросом".
_>В принципе вариант с текстовыми путями и запросами вида like '/path/%' это позволяет, но я думаю не стоит объяснять в чём заключается кривизна данного полухака. Вo многих nosql БД всё получается в один запрос без всяких хаков, так сказать by design. Ну и насколько я слышал (сам не пользовался) в некоторые реляционные СУБД (например в тот же PostreSQL) добавляли специальные возможности (типы) для более вменяемой реализации подхода с путями. . Но во-первых это уже не SQL, так что точно несовместимо ни с чем.
И опять facepalm. Перед тем, как фонтанировать невежеством, ознакомьтесь с common table expressions. Это вполне себе ANSI SQL, и он поддерживается во всех основных движках. Если уж хочется поговорить про нестандартные расширения SQL для работы с деревьями, то ознакомьтесь с connect by из Oracle.
_>А во-вторых даже вариант с нестроковыми путями всё равно уступает нативным графам по удобству. Хотя кое-как уже работать можно, если конечно согласиться на привязку к конкретной СУБД.
Замечательно. Вы поверхностно изучили один способ представления иерархических данных в SQL, и позволяете себе делать утверждения космического масштаба.
NoSQL решения, на которые вы ссылаетесь, ложатся навзничь, стоит отойти от единственного типа запросов и/или выйти в размере хранимых данных за пределы RAM.
А SQL продолжит работать и отдавать данные с приемлемой производительностью.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Накладных расходов на что конкретно? Они там разные. Расход при первом выполнении, когда парсится ЕТ и компилируются мепперы весьма приличный, десятки и сотни миллисекунд. Расход на вычисление хеша ET на среднем железе порядка сотен микросекунд ЕМНИП, расход на меппинг неотличим от полностью рукопашного кода без каких либо абстракций, т.е. скорее отрицательный, чем положительный, так как руками такое обычно никто не выписывает.
Вот. Это уже действительно интересная техническая информация. Спасибо.
А запросы кэшируются всегда целиком? Ну т.е. если скажем в запросе поменяется значение id в "where id=xxx", то запрос будет заново парситься и компилироваться или нет?
Пока мой комментарий из этих цифр: для быстрых sql запросов смысл снижать накладные расходы за счёт linq всё же есть.