Re[40]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.15 00:08
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, gandjustas, Вы писали:


_>>>Это ты похоже бредишь, если считаешь что размер кэша и основной памяти должен быть одинаковым. Даже если не можешь провести аналогию с классическими кэш системами, то хотя бы просто взглянул на дефолтное значение параметра размера кэша в обсуждаемых СУБД.

G>>А с чего ты взял что я так считаю?

_>Потому что говоришь о притеснение кэшем памяти отведённой под таблицы. ))) В то время как на практике это совсем разные числа.

Числа может быть и разные, а память то одна. Каждые 4кб памяти скушанной кешем или еще чем-то приводят к дополнительным чтениям с диска. Ты с этим споришь?

_>Ты как-то совсем не уважаешь авторов СУБД.

Авторов очень уважаю, ну кроме mysql, они умудрились такое говно сделать, что непонтяно какими мотивами руководствовались.

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

Интересно как кеш узнает что часто запрашивается? Статистику собирает?

_>>>Повторюсь ещё раз: чем больше база, тем лучший будет эффект от включения кэша. Если тебе это не очевидно, то я даже не знаю о чём можно ещё говорить. )))

G>>Архитектура баз данных говорит нам ровно обратное, о чем еще ты хочешь поговорить?
G>>Или можешь объяснишь нам как кеш помогает уменьшить чтение с диска если приходят разные запросы?

_>Твоё понимание кэша справедливо только для случая запросов вида select * from ... where id=xxx; причём при условие, что у нас вероятность запросов с id=xxx имеет равномерное распределение. Я думаю ты сам понимаешь, что в реальных системах картина совсем другая.

Да что ты? А какая? В корпоративных приложениях обычно crudl и большая часть запросов — получение списка (кешировать бесполезно, так как отдаваемые данные сосуществуют покрывающему индексу), на вором месте просмотр сущности (как раз выбор по id, что тоже бесполезно кешировать ибо совпадает с кластерным индексом). Даже если взять консьюмерские мобильные приложения, то они в бекэнде имеют базу и большая часть запросов идет с фильтром по userid. Естественно у каждого пользователя разный userid.
Re[38]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.15 00:13
Оценка: +1
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, gandjustas, Вы писали:


G>>Если ты возвращаешь объект, то должен поднять все его поля из базы, это значит нет проекций и все индексы идут нафиг, повышеная нагрузка на сеть и затраты на материализацию. И это все даже если тебе просто имя пользователя вывести нужно. А если у тебя 100500 методов под каждый запрос, то поддерживать их — ад, банальное добавление постраничной разбивки и сортировки в dbGetUsers требует правки кучи мест.


_>Это был просто пример, а не универсальное решение. Ещё раз повторюсь: сделать универсальное оптимальное решение невозможно. Однако сделать это для конкретной задачи и БД нет никаких проблем.

Тем не менее у авторов Linq получилось сделать универсальный типизированный api для доступа к данным. Оптимальность его вызывает сомнения, но накладные расходы компенсируются высокой эффективностью сгенерированных запросов.

G>>Вот ты сам и показал зачем IQueryable нужен практически везде.

_>А вот IQueryable — это как раз попытка сделать универсальное решение. Более менее конечно же работает, но естественно будет всегда хуже частных решений.
С чего ты взял что "всегда хуже"? Ты не смог лучше ничего показать, есличо.

_>В этом собственно и смысл слоя абстракции БД — он свой в каждом приложение. Естественно всегда были попытки как-то это автоматизировать (так и родились ORM), но всё равно добиться полноценной замены написанного человеком не выходит.

На практике ровно наоборот, самописные методы типа GetUser прекрасно заменяются ORM, так еще и эффективность приложения повышают. А Linq2DB умудряется даже банальный мэппинг делать быстрее, чем врукопашную написанный. Ты видимо никогда не делал приложения, работающие с данными раз говоришь такие глупости.
Re[42]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.15 00:22
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Как видишь, "не всё так однозначно" (c) — используя кэш всё-таки можно увеличить "свободную память"

Речь об автокеше, а не о любом кеше.

EP>>>Вариант 2. Запрос с фильтрацией, с выводом всех столбцов. Без кэша результата, даже если загружены в память только минимально необходимые страницы, то они всё равно будут содержать неиспользуемые строки, помимо этого в памяти будут сидеть страницы соответствующего индекса.

EP>>>Вариант 3. Запрос выводит все строки*столбцы, но в определённом порядке. В этом случае память также будет расходоваться под индекс, а в случае готового результата — нет, не говоря уже о том что линейный обход памяти на порядок (а бывает и на порядки) эффективней случайного.
G>>Ты точно знаешь как базы работают? Про покрывающие индексы не слышал?

EP>И чем они помогут в случае динамических фильтров и динамических предикатов?

В случае если пользователь может "накликать" любой запрос и кэш не поможет. Hit ratio будет низким.
Но в реальном приложении "произвольный" запрос к таблицам на миллионы строк можно встретить очень нечасто.

EP>Я уже писал ранее что с СУБД вообще не приходится работать. Это, тем не менее, не освобождает оппонента от необходимости аргументировать свою позицию

Тогда специально для тебя еще раз объясняю. Задача СУБД — оптимизировать чтение с диска. Чтение одной "страницы" занимает 5-10 мсек, сколько там операций в памяти можно сделать за это время?

G>>>>Когда данные уж в ОП, то там различия минимальные, доли миллисекунд.

EP>>>Элементарный пример — есть таблица в 30 гигабайт, для неё нужно сделать агрегирование с результатом в одну строчку. Угадай что будет быстрее — закэшированный результат или полное вычисление?
G>>Индексированное представление, а кэш не нужен.
EP>Для динамических запросов, с динамическими формулами?
См выше, hit ratio низкий, кэш практически бесполезен. Для olap — агрегация по любым срезам — применяются отдельные системы, которые имеют совершенно другие способы хранения и расходуют очень много памяти.

EP>>>Пример конечно экстремальный, но поинт простой — готовый результат может быть в разы, а то и на порядки быстрее чем сырые данные. Причём не теряет актуальность даже в если до DB существенное latency — например в том случае если запросов много.

G>>Походу ты действительно не знаешь как работают базы данных.
EP>Аргументов как всегда не будет?
Я тебе их уже по три раза привел. Ты же всегда апеллируешь к теории. Увы, с теорией, особенно недоказанной спорить сложно. Практических примеров у тебя нет. Можно лишь констатировать факт, что я немного больше знаю и имею больше опыта про субд и кеширование, поэтому твои теоретические выкладки не могу принять.

G>>Не продолжай пожалуйста.

EP>Давай, удачи, слив засчитан
Тебе, конечно, никто не мешает считать себя умнее, но умнее от этого ты не станешь. Увы.
Re[43]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 20.04.15 01:41
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>И чем они помогут в случае динамических фильтров и динамических предикатов?

G>В случае если пользователь может "накликать" любой запрос и кэш не поможет. Hit ratio будет низким.
G>Но в реальном приложении "произвольный" запрос к таблицам на миллионы строк можно встретить очень нечасто.

Тем не менее, вполне реальные use-case'ы для кэширования.

EP>>Я уже писал ранее что с СУБД вообще не приходится работать. Это, тем не менее, не освобождает оппонента от необходимости аргументировать свою позицию

G>Тогда специально для тебя еще раз объясняю. Задача СУБД — оптимизировать чтение с диска.

1. Одна из задач, далеко не единственная. Причём это низкоуровевая постановка задачи, а высокоуровневая звучит как — оптимизировать скорость доступа к данным.
2. Я изначально рассмотрел два аспекта
Автор: Evgeny.Panasyuk
Дата: 19.04.15
: в первом существенно то что кэш занимает меньше памяти чем заняли бы эквивалентные страницы (и возможно не поместились бы, либо были вымыты из памяти и т.п.), а во втором сравнивается скорость в том случае когда и кэш и эквивалентные страницы полностью помещаются в пмять. Так вот, здесь мы находимся как раз во втором варианте — зачем ты вообще сюда пытаешься приплести чтение с диска?

G>Чтение одной "страницы" занимает 5-10 мсек,


Это HDD, причём в случае случайного доступа — если же грузится пачка последовательных страниц, то намного меньше
Для БД также используют SSD.

G>сколько там операций в памяти можно сделать за это время?


При последовательном доступе в одно ядро можно выдуть около десяти гигабайт за одну секунду, причём особо не напрягаясь.
За десять миллисекунд — около ста мегабайт. Если же результат обработки сотни мегабайт уже готов, то очевидно различия будут не доли миллисекунд как ты опрометчиво заявлял ранее.

EP>>>>Пример конечно экстремальный, но поинт простой — готовый результат может быть в разы, а то и на порядки быстрее чем сырые данные. Причём не теряет актуальность даже в если до DB существенное latency — например в том случае если запросов много.

G>>>Походу ты действительно не знаешь как работают базы данных.
EP>>Аргументов как всегда не будет?
G>Я тебе их уже по три раза привел. Ты же всегда апеллируешь к теории. Увы, с теорией, особенно недоказанной спорить сложно.

А что тут "не доказано"? То что закэшированный запрос по данным в памяти может отличаться не на доли миллисекунд от обычного обхода (утверждение №1)? Вроде очевидно

G>Практических примеров у тебя нет.


То есть без практических примеров ты не можешь понять утверждение №1?

G>Можно лишь констатировать факт, что я немного больше знаю и имею больше опыта про субд и кеширование


Я об этом сразу сказал, можешь констатировать это хоть в каждом сообщении — аргументации это не добавит.

G>поэтому твои теоретические выкладки не могу принять.


Да не принимай — я привёл технические "выкладки". Если ты видишь в них ошибку, то тебе достаточно привести технический контраргумент, а не разглагольствовать на тему — можешь ли ты это принять или нет

G>>>Не продолжай пожалуйста.

EP>>Давай, удачи, слив засчитан
G>Тебе, конечно, никто не мешает считать себя умнее, но умнее от этого ты не станешь. Увы.

Вот уже и лирика пошла, слабо оставаться в техническом русле?
Отредактировано 20.04.2015 1:45 Evgeny.Panasyuk . Предыдущая версия .
Re[32]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.04.15 05:48
Оценка: +2
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, Слава, Вы писали:


С>>SQL и Linq — это как раз очень высокий уровень декларативного программирования. SQL вообще обогнал свое время на 30 лет.


_>Для работы с массивами очень не плохой уровень, да. Но и только. Даже реализация других типов данных уже становится проблематична. А уж об использование в роли внутреннего API приложения вообще нечего говорить, т.к. не реализована возможность добавления специфики приложения. Это про SQL была речь. А конкретная реализация по имени linq вообще ужасна своей тормознутостью. Недаром во всех ответственных местах её заменяют на банальный совсем низкоуровневый for.

Непрерывный facepalm.
SQL — одно из гениальнейших изобретений, в моём личном hall of fame идёт сразу после концепции "вызов подпрограммы".
Проблема его — в том, что его так и не развили до полноценного языка программирования, не дав средств управления сложностью.
В рамках одного запроса он непревзойдён — встроенную в него механику вывода типов десятилетиями не удавалось догнать в промышленных языках программирования.
(Вот я, к примеру, до сих пор не вполне понимаю, каким образом эту проблему решает sqlpp). В основном из-за этого и сосали все основные ORM — они пытались уложить выразительную систему реляционных типов, существующую в SQL, в убогую модель номинативной типизации. Из-за этого и получались все эти "недозагруженные user" и прочий бред.

Linq решает основную проблему SQL, позволяя повысить повторное использование кода. Можно строить функции высшего порядка — принимать запросы и возвращать запросы.
Именно этого не хватает в SQL.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[40]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.04.15 06:15
Оценка: 2 (2) +2
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Элементарный пример — есть таблица в 30 гигабайт, для неё нужно сделать агрегирование с результатом в одну строчку. Угадай что будет быстрее — закэшированный результат или полное вычисление?
Нюанс — в том, что 100 клиентам с высокой вероятностью требуется 100 разных агрегирований.
Самая простая шутка месяца — клиент запрашивает сумму продаж за 2014 год. Это одно число, вот только определение 2014 года у всех разное, т.к. зависит от часового пояса клиента.
Как устроено первое выполнение такого запроса?
Клиент выполняет запрос, за ~500мс происходит roundtrip до веб-сервера, ещё 50мс обработка на веб-сервере, 100мс — раундтрип к базе данных, там мы делаем примерно 50000 IO операций (размер экстента — 64кб, предполагаем наличие покрывающего индекса по полям "дата продажи", "сумма продажи", а 30гб — это данные за 10 лет, т.е. объём чтения — 3GB).
Если у нас стоит RAID 10 из 15к RPM дисков, то можно справиться секунд за 30. Итого — примерно 31 секунда на результат.

Как устроено повторное выполнение такого запроса?
В наивной схеме мы снова бежим на сервер (500+50+100мс), на этот раз нужные 3GB у нас в страничном кэше, и мы отдаём ответ примерно за 750мс.
Нюанс: это значение мало зависит от того, в той же таймзоне новый клиент или нет, т.к. в худшем случае в кэше не хватает данных за 1 день, а это в пределах 10 мегабайт или 160 чтений — 100 мс. Естественно, мы предполагаем, что уж 3ГБ памяти у нас есть — обычные машинки, отданные под базы такого размера, тащат от 16 до 32ГБ RAM.

В простой, но надёжной схеме мы отдаём данные с expiration: never, потому что 2014 год закончился больше 1го квартала назад, и изменений в нём не будет.
Т.е. повторное обращение с того же клиента получит результат за 0мс.
Клиенты с пустым кэшем получают данные за 750 мс, и мы можем легко улучить этот результат, поставив reverse proxy перед нашим сервером приложений. Мы получим ответ за 500мс, при этом у нас будет гарантия изоляции СУБД от реальной нагрузки — даже если к нам будет приходить 1 миллион запросов в день, СУБД и сервер приложений увидят не более 30 запросов.
Если мы хотим улучшить характеристики для особенно интересных нам групп клиентов, то поставим региональные proxy и залудим GeoDNS. Теперь клиенты в популярных часовых поясах будут получать ответ за 50 миллисекунд. И всё это — за копейки, по сравнению с переделкой архитектуры приложения.

Что же будет, если мы попробуем применить "передовую технологию" кэширования результатов запросов в СУБД?
Во-первых, это замедлит операции СУБД, т.к. теперь все записи будут проверяться на предмет инвалидации кэша.
Во-вторых, СУБД придётся тратить время не только на разбор стейтмента, но и на попытки выяснить, покрывается ли он кэшем, или нет.
В-третьих, кэш результатов отъест немножко памяти у страничного кэша, снижая его hit ratio. Заранее угадать, сколько места отвести под этот кэш, довольно тяжело.
А самое печальное — в том, что мы всё ещё отдаём эти данные за 750мс, что в разы хуже 0мс, обеспеченных прозрачным кэшем HTTP-запросов. При этом размер HTTP-кэша автоматически растёт с ростом количества клиентов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.04.15 06:24
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>И чем они помогут в случае динамических фильтров и динамических предикатов?

На уровне базы динамические фильтры от нединамических неотличимы. Нет никакого специального синтаксиса для select, который выбирает "динамику".
Движок каждый раз сравнивает запрос с набором индексов, и выбирает оптимальный план. Если движок приличный, то он ещё и учитывает конкретные значения параметров запроса и статистику реальных данных для оценки селективности различных частей предикатов.

EP>Для динамических запросов, с динамическими формулами?

Индексированное представление — один из хороших вариантов сделать "прикладное кэширование", показав базе, какие производные данные мы ожидаем часто видеть в запросах.
И опять: вся мощь оптимизации движка позволяет нам получать высокую производительность независимо от "степени динамичности".
Если я сделал indexed view для select SalesDate, sum(SalesAmount) as TotalAmount from sales group by SalesDate, то я вполне могу скармливать в движок запросы с различными параметрами — типа "покажи мне день с самыми высокими продажами за 2013", или "покажи мне помесячные продажи за 2013/2014" — и всё ещё я буду получать бенефиты от преагрегации и выбора уместных индексов.
То есть я не прибиваю гвоздями один конкретный результат одного конкретного запроса, а ввожу ещё один уровень кэширования, который помогает в широком классе запросов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[34]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.04.15 06:38
Оценка: 1 (1) +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>С чего бы это?
EP>Я говорю о том, что с LINQ можно срезать лишний runtime жир, не потеряв при этом способность генерировать тот же результат. Согласен?
С этим спорить трудно. Если внимательно рассмотреть все этапы генерации SQL в приложении, основанном на linq, то становится понятно, что некоторые вещи можно бы и улучшить.
А вот от некоторых избавиться не удастся.
Скажем, конверсия AST в SQL устроена так, что в ней не очень большие abstraction penalties. Ненамного больше, чем в склейке строк.
Но при усложнении AST генерация SQL по дереву продолжает порождать корректный SQL, а склейка строк начинает всё больше огребать.

Идея попытаться статически сгенерировать все варианты SQL запросов мне не кажется практичной. Это в некотором смысле эквивалентно идее запилить отдельные версии хранимок под каждый интересный нам случай. Т.е. code bloat будет существенным (т.к. количество вариантов при добавлении нового параметра растёт экспоненциально), а выигрышь по сравнению с честным обходом дерева будет незначительным.
Рассуждения про расположение узлов AST в памяти я считаю нерелевантными. Из всех cache miss, которые могут произойти в цепочке обработки запроса клиента, самые незначительные — это промахи мимо L1/L2 в процессоре сервера приложений.

Что можно было бы соптимизировать — это процесс построения фрагментов Expression Tree. Вот его вполне можно сделать в compile-time, т.к. там ничего особенно рантаймного нету.
Но шансы на то, что это сделают — микроскопические. Реальные потери времени на это можно заметить только в синтетических тестах; поэтому в очереди на улучшение это изменение будет среди последних.
Тем более, что мы сразу же нарываемся на массу ограничений. Например, вот эта "тормозная динамика" позволяет нам спокойно делить код на независимые единицы компиляции. А плюсовому компилятору нужно видеть тела всех шаблонных классов/методов одновременно, иначе вся магия сломается. Это мешает нам пилить код на проекты и адски замедляет компиляцию.
В итоге, для обеспечения continuous integration, приходится применять титанические усилия, стоимость которых очень трудно окупить экономией миллисекунд на запросах, которые исполняются десятки секунд.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[38]: EntityFramework - тормоз
От: Mamut Швеция http://dmitriid.com
Дата: 20.04.15 07:03
Оценка: +1
M>>Любой «независимый от баз данных» слой сможет покрыть только общий для всех баз данных функционал + некоторое количество хаков для некоторых вещей. Ну типа генерация последовательностей для баз данных, где последовательностей не существует. Или грязные хаки для windowing functions.

_>Безусловно движку, умеющему работать с разными СУБД, приходится ограничиваться пересечением функционала этих СУБД. Но на самом деле этого обычно вполне достаточно, т.к. во всех нормальных СУБД есть всё нужное.


Покажи мне windowing functions в MySQL.
Покажи мне generate_series не в PostgreSQL.


Хот да, неизвестно же, что ты считаешь «нормальными базами данных»

_>Там основная проблема скорее в другом — в разных СУБД эта функциональность может по разному подключаться.


_>Такими темпами он может когда-нибудь выйти в однозначные лидеры и тогда можно будет спокойно затачиваться под него — вот будет счастье для авторов всяких движков. ))) Но пока до этого ещё далеко.


Мдеее. Теоретики такие теоретики. «Нормальные базы данных», «всего лишь реализовать функционал», «однозначные лидеры».

Достаточно того, что на первых трех местах несовместимые друг с другом по функционалу базы данных.

Можно начать, например, с hierarchical queries и windowing functions. Ну или, повторю, с generate_sequence.


dmitriid.comGitHubLinkedIn
Отредактировано 20.04.2015 7:04 Mamut [ищите в других сетях] . Предыдущая версия .
Re[48]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 20.04.15 08:34
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Если сделать допущение, что у одного и того же запроса узлы в памяти располагаются последовательно


В условиях GC?

EP>Плюс надо будет "нормализировать" указатели-дуги, чтобы они не зависели от начального адреса.


В условиях GC?

EP> Плюс отказ от виртуальных функций


Для этого не нужен unsafe.
Re[44]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 20.04.15 08:34
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Никто и не просит точные цифры. Но по порядку величины


Порядок я тебе сказал.
Re[38]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 20.04.15 08:34
Оценка: +1
Здравствуйте, alex_public, Вы писали:

_>О том и речь — реляционная модель подходит не всегда.


Если не подходит реляционная модель, значит не подходит и РСУБД.

_>Ну меня больше интересует не конкретный синтаксис, а изменит ли это накладные расходы по отношению к варианту с просто int'ом.


С точностью до времени выделения памяти и работы конструктора.

_>Ну естественно подразумевается, что и весь остальной доступ к БД реализован через подобные функции.


Ну вот за это, если ты еще не понял, и надо расстреливать.

_>А дальше возможно сделать несколько альтернативных реализаций, в зависимости от используемого движка для хранения данных.


Возмоно, но на практике никому не нужно. Итого овердизайн в чистом виде.

_>Это всё общие слова ни о чём.


Это конкретные слова о чем. Если ты этого не понимаешь — могу только посочувствовать.

_> На практике большинство известных движков реализовано именно с помощью подобного слоя абстракции бд и отлично работают.


Каких движков? О чем ты?

НС>>Ненужная и вредная работа и раздутый на ровном месте код.

_>Т.е. удобный API в терминах приложения

Чем он удобный? Тем что его на каждый чих править надо? Или тем что классы в возвращаемом результате провоцируют на нарушение инвариантов?

_> и отсутствие никчемных накладных расходов — это ненужная и вредная работа?


Лишний слой это не отсутствие, это наоборот — присутствие.
Re[40]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 20.04.15 09:00
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Почему перевести? ) Я и старую тему не бросил.


Какую старую? Ты сабж то прочти?

_> Однако это не мешает пообсуждать в ответвление темы соседний вопрос.


Интересующие тебя проблемы с linq 2 objects в решарпере не имеют вообще никакого отношения к linq 2 db. Поэтому это грубый перевод темы.
Re[33]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 20.04.15 09:00
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>SQL — одно из гениальнейших изобретений, в моём личном hall of fame идёт сразу после концепции "вызов подпрограммы".


Как концепция разве что. Как конкретный язык — на редкость унылое гавно.

S>Проблема его — в том, что его так и не развили до полноценного языка программирования, не дав средств управления сложностью.


Угу, то есть не решили основную задачу ЯВУ.

S>В рамках одного запроса он непревзойдён — встроенную в него механику вывода типов десятилетиями не удавалось догнать в промышленных языках программирования.


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

S>Linq решает основную проблему SQL, позволяя повысить повторное использование кода. Можно строить функции высшего порядка — принимать запросы и возвращать запросы.


Не только. Как минимум есть еще и IQueryable, который позволяет делать на две головы более гибкое API минимальными усилиями. А его ведь можно еще и наружу выставлять, через OData к примеру, или через WCF расширение linq2db.
Re[41]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 20.04.15 09:47
Оценка:
Здравствуйте, Sinclair, Вы писали:

EP>>Элементарный пример — есть таблица в 30 гигабайт, для неё нужно сделать агрегирование с результатом в одну строчку. Угадай что будет быстрее — закэшированный результат или полное вычисление?

S>Нюанс — в том, что 100 клиентам с высокой вероятностью требуется 100 разных агрегирований.

Я говорю что для кэширования есть use-case'ы — ничего не говоря о том насколько они часто встречаются. Делаю это чтобы показать, что безапелляционные заявления о том, что при кэше чтение с диска всегда будет чаше — слишком категоричны.

S>Самая простая шутка месяца — клиент запрашивает сумму продаж за 2014 год. Это одно число, вот только определение 2014 года у всех разное, т.к. зависит от часового пояса клиента.


И что должен показать этот конкретный пример? Тем более с добавлением внешнего кэширования? Он как-то показывает то, что при кэше, в любом use-case'е, чтение с диска всегда будет чаше?
С тем что где-то кэшировние может пойти во вред — я не спорю, также не спорю что где-то более приемлемым будет внешнее кэширование, также не спорю о процентном соотношении разных случаев
Re[43]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 20.04.15 09:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

EP>>И чем они помогут в случае динамических фильтров и динамических предикатов?

S>На уровне базы динамические фильтры от нединамических неотличимы. Нет никакого специального синтаксиса для select, который выбирает "динамику".
S>Движок каждый раз сравнивает запрос с набором индексов, и выбирает оптимальный план. Если движок приличный, то он ещё и учитывает конкретные значения параметров запроса и статистику реальных данных для оценки селективности различных частей предикатов.

Здесь под динамическими фильтрами и предикатами — подразумеваются выражения неизвестные во время сборки приложения. Их "специальность" в том, что для них нельзя построить индексы заранее, а не в том что у них какой-то особенный синтаксис.

EP>>Для динамических запросов, с динамическими формулами?

S>Индексированное представление — один из хороших вариантов сделать "прикладное кэширование", показав базе, какие производные данные мы ожидаем часто видеть в запросах.

Как создать индекс для динамических формул?

S>И опять: вся мощь оптимизации движка позволяет нам получать высокую производительность независимо от "степени динамичности".


Не будет никакой высокой производительности для выражений задающихся извне.
Отредактировано 20.04.2015 9:57 Evgeny.Panasyuk . Предыдущая версия .
Re[44]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.15 10:33
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, gandjustas, Вы писали:


EP>>>И чем они помогут в случае динамических фильтров и динамических предикатов?

G>>В случае если пользователь может "накликать" любой запрос и кэш не поможет. Hit ratio будет низким.
G>>Но в реальном приложении "произвольный" запрос к таблицам на миллионы строк можно встретить очень нечасто.

EP>Тем не менее, вполне реальные use-case'ы для кэширования.

На которых кэш не будет работать если считать любую комбинацию равновероятной. Но в реальном мире равномерного распределения вероятностей почти никогда не встретишь, а при нормальном распределении можно построить индексы, которые покроют 80% запросов, а на остальные 20% забить. И это будет в разы эффективнее кеша в базе.

EP>>>Я уже писал ранее что с СУБД вообще не приходится работать. Это, тем не менее, не освобождает оппонента от необходимости аргументировать свою позицию

G>>Тогда специально для тебя еще раз объясняю. Задача СУБД — оптимизировать чтение с диска.

EP>1. Одна из задач, далеко не единственная. Причём это низкоуровевая постановка задачи, а высокоуровневая звучит как — оптимизировать скорость доступа к данным.

Данные лежат на диске если что.

EP>2. Я изначально рассмотрел два аспекта
Автор: Evgeny.Panasyuk
Дата: 19.04.15
: в первом существенно то что кэш занимает меньше памяти чем заняли бы эквивалентные страницы (и возможно не поместились бы, либо были вымыты из памяти и т.п.), а во втором сравнивается скорость в том случае когда и кэш и эквивалентные страницы полностью помещаются в пмять. Так вот, здесь мы находимся как раз во втором варианте — зачем ты вообще сюда пытаешься приплести чтение с диска?

Потому что когда база умещается целиком в память, о вообще нет смысла считать. Время раундтрипа до базы окажется выше разницы между отдачей результата из кеша и из страниц в памяти. Даже при высоком hit ratio.

G>>Чтение одной "страницы" занимает 5-10 мсек,


EP>Это HDD, причём в случае случайного доступа — если же грузится пачка последовательных страниц, то намного меньше

А у тебя есть уверенность, что тебе нужна последовательная пачка? Станицы в файле данных обычно выделяются случайным образом, так как выделяется только первая свободная. Если регулярно ребилдить индексы, то можно добиться линейности чтений, но на очень незначительное время. Так что можно смело считать, что большинство чтений с диска — случайны.


EP>Для БД также используют SSD.

И что? Даже с SSD чтение с диска на порядки медленнее чем операции в памяти.

G>>сколько там операций в памяти можно сделать за это время?


EP>При последовательном доступе в одно ядро можно выдуть около десяти гигабайт за одну секунду, причём особо не напрягаясь.

EP>За десять миллисекунд — около ста мегабайт. Если же результат обработки сотни мегабайт уже готов, то очевидно различия будут не доли миллисекунд как ты опрометчиво заявлял ранее.
Это ты о чем сейчас?


EP>>>>>Пример конечно экстремальный, но поинт простой — готовый результат может быть в разы, а то и на порядки быстрее чем сырые данные. Причём не теряет актуальность даже в если до DB существенное latency — например в том случае если запросов много.

G>>>>Походу ты действительно не знаешь как работают базы данных.
EP>>>Аргументов как всегда не будет?
G>>Я тебе их уже по три раза привел. Ты же всегда апеллируешь к теории. Увы, с теорией, особенно недоказанной спорить сложно.

EP>А что тут "не доказано"? То что закэшированный запрос по данным в памяти может отличаться не на доли миллисекунд от обычного обхода (утверждение №1)? Вроде очевидно

Также очевидно, что память скушанная кешем приведет к повышению количества чтений с диска. Но тебе почему-то неочевидно.
Также очевидно что при равной вероятности любых запросов hit ratio будет нулевым и кеш по факту не будет работать, а при неравномерном распределении та же проблема решается индексами. Но тебе это тоже неочевидно.
Причем этим очевидным вещам ты противопоставляешь чисто теориетические выкладки. Приведи хоть один результат тестов, который подтверждает твои слова.

G>>Практических примеров у тебя нет.

EP>То есть без практических примеров ты не можешь понять утверждение №1?
Понять != поверить.

G>>Можно лишь констатировать факт, что я немного больше знаю и имею больше опыта про субд и кеширование

EP>Я об этом сразу сказал, можешь констатировать это хоть в каждом сообщении — аргументации это не добавит.
Это я к тому, что твоя агрументация слаба.

G>>поэтому твои теоретические выкладки не могу принять.

EP>Да не принимай — я привёл технические "выкладки". Если ты видишь в них ошибку, то тебе достаточно привести технический контраргумент, а не разглагольствовать на тему — можешь ли ты это принять или нет
Я тебе привел уже несколько раз и в этом посте тоже. Ты их банально игнорируешь.

G>>>>Не продолжай пожалуйста.

EP>>>Давай, удачи, слив засчитан
G>>Тебе, конечно, никто не мешает считать себя умнее, но умнее от этого ты не станешь. Увы.
EP>Вот уже и лирика пошла, слабо оставаться в техническом русле?
То есть

слив засчитан

ты считаешь "техническим руслом" ? Тогда я из него никогда и не выходил.
Re[44]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.15 10:40
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Sinclair, Вы писали:


EP>>>И чем они помогут в случае динамических фильтров и динамических предикатов?

S>>На уровне базы динамические фильтры от нединамических неотличимы. Нет никакого специального синтаксиса для select, который выбирает "динамику".
S>>Движок каждый раз сравнивает запрос с набором индексов, и выбирает оптимальный план. Если движок приличный, то он ещё и учитывает конкретные значения параметров запроса и статистику реальных данных для оценки селективности различных частей предикатов.

EP>Здесь под динамическими фильтрами и предикатами — подразумеваются выражения неизвестные во время сборки приложения. Их "специальность" в том, что для них нельзя построить индексы заранее, а не в том что у них какой-то особенный синтаксис.


Ты предполагаешь, что любой запрос равновероятен? Тогда чем поможет кеш? А если не равновероятен, то в чем проблема построить индексы?


EP>>>Для динамических запросов, с динамическими формулами?

S>>Индексированное представление — один из хороших вариантов сделать "прикладное кэширование", показав базе, какие производные данные мы ожидаем часто видеть в запросах.

EP>Как создать индекс для динамических формул?

Нету в SQL динамических формул, они все для СУБД одинаковые. Но в реальной жизни окажется, что одни предикаты встречаются чаще других. Например для таблиц с историей данных чаще будут встречаться предикаты с датой, чем с любым другим полем и нам ничего не помешает сделать индекс по дате, который ускорит львиную долю запросов. А если часто встречаются агрегаты по определенным полям, то мы можем сделать индексированное представление, которое ускорит нам запросы.

S>>И опять: вся мощь оптимизации движка позволяет нам получать высокую производительность независимо от "степени динамичности".

EP>Не будет никакой высокой производительности для выражений задающихся извне.
Опять таки если считать что все запросы равновероятны. Но тогда и кеши не помогут (вообще никакие).
Re[35]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 20.04.15 11:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Но при усложнении AST генерация SQL по дереву продолжает порождать корректный SQL, а склейка строк начинает всё больше огребать.


А причём здесь вообще склейка строк?

S>Идея попытаться статически сгенерировать все варианты SQL запросов мне не кажется практичной.


А вручную проставлять компиляцию каждого варианта запроса?

S>Это в некотором смысле эквивалентно идее запилить отдельные версии хранимок под каждый интересный нам случай. Т.е. code bloat будет существенным (т.к. количество вариантов при добавлении нового параметра растёт экспоненциально),


В долгоиграющем приложении, при кэшировании запросов, размер кэша тоже будет существенным (хотя можно поставить threshold + priority queue). Причём кэш будет пересоздаваться в каждом работающем процессе, в то время как при предварительной генерации процессы будут разделять физические страницы памяти с запросами.
Тем не менее, можно найти плюсы/минусы в обоих вариантах, но перейти из статики в динамику (например когда вариантов для какого-то из запросов получается очень много) намного проще чем наоборот.

S>а выигрышь по сравнению с честным обходом дерева будет незначительным.


Может и незначительным, но выше говорят
Автор: AK107
Дата: 19.04.15
что всё-таки приходится использовать compiled query.

S>Рассуждения про расположение узлов AST в памяти я считаю нерелевантными. Из всех cache miss, которые могут произойти в цепочке обработки запроса клиента, самые незначительные — это промахи мимо L1/L2 в процессоре сервера приложений.


Чем дальше данные от L1, тем существеннее penalty при произвольном обходе.

S>Что можно было бы соптимизировать — это процесс построения фрагментов Expression Tree. Вот его вполне можно сделать в compile-time, т.к. там ничего особенно рантаймного нету.


Я именно это и сказал в первом же своём сообщении:

http://rsdn.ru/forum/flame.comp/6014522.1


EP>Если не нравится экспоненциальное количество запросов в исполняемом файле, то можно добавить динамики. Да, при этом запрос будет частично строится в runtime (с возможным кэшированием), но при этом не будет дорогой runtime reflection — в ней тут нет принципиальной необходимости, достаточно compile-time reflection.


S>Тем более, что мы сразу же нарываемся на массу ограничений. Например, вот эта "тормозная динамика" позволяет нам спокойно делить код на независимые единицы компиляции.


Опять таки, добавить динамику можно по необходимости.

S>А плюсовому компилятору нужно видеть тела всех шаблонных классов/методов одновременно, иначе вся магия сломается. Это мешает нам пилить код на проекты


Проектом может быть header-only библиотека — вполне распространённая практика.

S>и адски замедляет компиляцию.


Компиляция адски замедляется из-за особенностей метапрограммирования C++, под которое язык вообще говоря не затачивался. Я же говорю в общем про EDSL/DSL, не ограничиваясь рамками C++ — например предполагаю что в языках с первоклассным метапрограммированием типа D или Nemerle компиляция будет намного быстрее.
Re[49]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 20.04.15 11:50
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>Если сделать допущение, что у одного и того же запроса узлы в памяти располагаются последовательно

НС>В условиях GC?

Если они создаются в одном месте — то да, в условиях Compacting GC это будет самый вероятный вариант. Для других можно сделать fallback.

EP>>Плюс надо будет "нормализировать" указатели-дуги, чтобы они не зависели от начального адреса.

НС>В условиях GC?

При последовательном unsafe обходе памяти, если натыкаемся на указатель — то хэшируем не сам адрес, а его нормализированную форму.
Но, чем на более низком уровне мы делаем реализацию — тем естественно больше появляется дополнительных ньюансов типа перемещения памяти/fixed.

EP>> Плюс отказ от виртуальных функций

НС>Для этого не нужен unsafe.

Он нужен для обхода памяти.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.