Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Serginio1, Вы писали:
S>>Где здесь Y-комбинатор?
V>Дочитай до конца — вся статья ради него.
S>>Я использовал в своей практике S>>
S>>delegate int Recursive(Recursive r, int n);
V>...
S>>
V>А чем не угодила обычная рекурсивная ф-ия? V>Мы-то тут просто развлекаемся, а в реальной практике что такого могло произойти, что по-другому ты не выкрутился?
Нужен был автомат, состояние это функция причем асинхронную, которая возвращает функцию S>> Можно ссылочку на то, что создается новый делегат?
V>Там же по твоей ссылке на каждой итерации Y-комбинатора создаётся новый экземпляр замыкания и для его вызова создаётся экземпляр делегата. V>Дочитай до конца.
Ну если есть захват переменных то да. Просто в таком виде это будет автомат на yeld ах. В простонаречии IEnumerable
Это во многих случаях предпочтительнее рекурсии.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
V>>А чем не угодила обычная рекурсивная ф-ия? V>>Мы-то тут просто развлекаемся, а в реальной практике что такого могло произойти, что по-другому ты не выкрутился? S>Нужен был автомат, состояние это функция причем асинхронную, которая возвращает функцию
Угу, это один из способов представления состояний автомата — через указатель на ф-ию.
Я так периодически делаю на плюсах.
Но на C# можно аналогично, верно?
V>>Там же по твоей ссылке на каждой итерации Y-комбинатора создаётся новый экземпляр замыкания и для его вызова создаётся экземпляр делегата. V>>Дочитай до конца. S> Ну если есть захват переменных то да. Просто в таком виде это будет автомат на yeld ах. В простонаречии IEnumerable S>Это во многих случаях предпочтительнее рекурсии.
Ну да, если сравнивать с Y-комбинатором, то yeld выглядит катастрофически предпочтительней, как грится. ))
Здравствуйте, Ikemefula, Вы писали:
V>>Я хотел услышать от коллеги, почему в батчах не могут быть "качественные запросы"? I>Я тоже хочу услышать объяснение, каким же чудом появится этот качественный запрос в твоем случае.
Так в чем проблема, ты будешь колоться или будешь вокруг да около ходить?
что тебя смущает-то?
Здравствуйте, vdimas, Вы писали:
V>>>Я хотел услышать от коллеги, почему в батчах не могут быть "качественные запросы"? I>>Я тоже хочу услышать объяснение, каким же чудом появится этот качественный запрос в твоем случае.
V>Так в чем проблема, ты будешь колоться или будешь вокруг да около ходить?
Свой ответ я тебе дал — ты его скипнул.
V>что тебя смущает-то?
Меня смущает, что ты свою версию никак объяснить не можешь, только общие слова "сервер всё сам", "девелопер всё сам", "что хочу, то и пишу".
Здравствуйте, vdimas, Вы писали:
V>Если использовать транслятор с твоего языка на обычный, то выглядит как очередная просьба объяснить непонимающему предмет.
Опять ты все напутал, не предмет, а что ты там себе придумал =) Но для тебя и это представляет проблему ))
V>Я готов обсуждать предметно и обсуждаю.
Ты себе льстишь ) Как мы уже выяснили, ты даже не очень хорошо помнишь и понимаешь, что сам же и написал.
V>На любые твои азбучные истины были даны ответы.
Только не о том о чем спрашивали, после чего ты ловко свел разговор на личности, как и в этот раз. )
Но пора бы тебе понять, что и в таком ключе тебе ничего не светит ))
V>Еще и врать изволим.
Да, изволите ) К счастью ты врешь только сам себе, раз ты это осознал, то сделал первый шаг к выздоровлению =)
V>Ветка на месте, мои ответы на месте.
Да, и там хорошо видно, что ни одного ответа по сути добиться от тебя не удалось.
Здравствуйте, Ikemefula, Вы писали:
V>>Так в чем проблема, ты будешь колоться или будешь вокруг да около ходить? I>Свой ответ я тебе дал — ты его скипнул.
Ты не ответил прямо на прямо заданный вопрос.
Бегаешь.
V>>что тебя смущает-то? I>Меня смущает, что ты свою версию никак объяснить не можешь
Я объяснил — есть сценарий последовательности запросов вместо одного.
Ты утверждаешь, что запросы в этой последовательности обязательно будут "плохие".
И вместо ответа на прямой вопрос "почему?" раздражаешь своей беготнёй.
Сказал "А" — говори "Б".
V>>>Многие вещи, прекрасно работающие в РСУБД в случае одного клиента, резко перестают работать уже при относительно среднем их трафике. G>>Например? V>Например хинты блокировок откуда вообще взялись?
Хинты взялись для поддержки нетиповых сценариев. Если в типовом ты используешь хинт значит делаешь что-то не так.
V>>>Сотни запросов в секунду для 99.99% наколенных поделок поверх современных РСУБД считается "хорошей нагрузкой". G>>Это смотря каких запросов. V>Глубокомысленное замечание.
Очень отражающее "наблюдаемую реальность". Потому что банально объем данных, необходимых для обработки запроса решает сильно больше, чем другие факторы. 100 запросов по ключу и 100 запросов самых популярных товаров за месяц дают сильно разную нагрузку.
V>>>А чтобы выйти хотя бы на 10 тыс нетривиальных запросов в сек, требуется уже высокая квалификация и целый комплекс мер по избавлению от плюшек РСУБД — избавляемся от внешних ключей, от лишних проверок на уникальность, от проверок на попадание значений в домен, происходит тотальное уничтожение ЛЮБЫХ триггеров, любых пользовательских ф-ий на стороне РСУБД и т.д. и т.п. до бесконечности. G>> G>>Прости, но такого отборного бреда давно не слышал.
V>На сайтах-магазинах с небольшой нагрузкой и не услышишь.
Думаешь база данных знает сайт магазина у тебя или что-то еще?
Ты хоть можешь сказать чем отличается план запросов с внешними ключами и без них? Как проверка на уникальность на план запроса влияет?
Ты просто не разбираешься в этом и продолжаешь говорить чушь.
Здравствуйте, gandjustas, Вы писали:
V>>>>Многие вещи, прекрасно работающие в РСУБД в случае одного клиента, резко перестают работать уже при относительно среднем их трафике. G>>>Например? V>>Например хинты блокировок откуда вообще взялись? G>Хинты взялись для поддержки нетиповых сценариев. Если в типовом ты используешь хинт значит делаешь что-то не так.
Вся 1С 8.x использует хинты во всех запросах для уменьшения гранулярности блокировок.
Что они делают не так?
V>>>>Сотни запросов в секунду для 99.99% наколенных поделок поверх современных РСУБД считается "хорошей нагрузкой". G>>>Это смотря каких запросов. V>>Глубокомысленное замечание. G>Очень отражающее "наблюдаемую реальность". Потому что банально объем данных, необходимых для обработки запроса решает сильно больше, чем другие факторы. 100 запросов по ключу и 100 запросов самых популярных товаров за месяц дают сильно разную нагрузку.
Вопрос тут в другом — как продолжить раздавать данные по лёгким частым запросам (пусть единицы тысяч раз в сек) с одновременно выполняющимися тяжелыми нечастыми (пусть их будет десятки/сотни в сек). В твоих "типовых сценариях", т.е. без ручного тюнинга гранулярности блокировок — никак. Если ты с этими известными сценариями не сталкивался, значит твой опыт с РСУБД весьма однобок.
G>>>Прости, но такого отборного бреда давно не слышал. V>>На сайтах-магазинах с небольшой нагрузкой и не услышишь. G>Думаешь база данных знает сайт магазина у тебя или что-то еще?
Думаю, что ты с серьёзной нагрузкой никогда не сталкивался.
Это видно по твоим рассуждениям не только в ответах мне.
В твоей реальности сотня запросов в секунду — это примерный предел нагрузки сверху.
Для таких нагрузок, действительно, ничего изобретать не надо, изкаробки само работает.
Пораздавал себе индексы как в учебниках и радуешься жизни.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>>>Многие вещи, прекрасно работающие в РСУБД в случае одного клиента, резко перестают работать уже при относительно среднем их трафике. G>>>>Например? V>>>Например хинты блокировок откуда вообще взялись? G>>Хинты взялись для поддержки нетиповых сценариев. Если в типовом ты используешь хинт значит делаешь что-то не так.
V>Вся 1С 8.x использует хинты во всех запросах для уменьшения гранулярности блокировок. V>Что они делают не так?
Они много чего не так делают. Вообще с точки зрения работы с БД это один из худших примеров.
Одна из ключевых проблем в том, что программист 1С не управляет конечной схемой БД и запросами. С одной стороны он и не может, потому что средств в конфигураторе мало, с другой стороны и не умеет, потому что квалификация типичного 1С программиста недостаточна чтобы эффективно работать с РСУБД.
В итоге получается что 1С умудряется дичайшее тормозить на совсем скромных объемах.
V>>>>>Сотни запросов в секунду для 99.99% наколенных поделок поверх современных РСУБД считается "хорошей нагрузкой". G>>>>Это смотря каких запросов. V>>>Глубокомысленное замечание. G>>Очень отражающее "наблюдаемую реальность". Потому что банально объем данных, необходимых для обработки запроса решает сильно больше, чем другие факторы. 100 запросов по ключу и 100 запросов самых популярных товаров за месяц дают сильно разную нагрузку.
V>Вопрос тут в другом — как продолжить раздавать данные по лёгким частым запросам (пусть единицы тысяч раз в сек) с одновременно выполняющимися тяжелыми нечастыми (пусть их будет десятки/сотни в сек). В твоих "типовых сценариях", т.е. без ручного тюнинга гранулярности блокировок — никак.
У тебя просто потрясающе сочетание тотального профанизма и самомнения.
1) Запросы на чтение не мешают друг другу, так как используют исключительно shared блокировки. Если у тебя не так, то ты делаешь какую-то фигню.
2) У тебя выставлены хреновые уровни изоляции. Для типичного приложения чаще всего подходит read commited snapshot в MS SQL. Он вообще не использует shared блокировки. По моему опыту repeatable read и serializable нужны в очень редких случаях и скорее внутри хранимых процедур, чем в пользовательском коде.
3) Если с уровнями изоляции все в порядке и запросы нормальные, а ты все равно испытываешь проблемы с блокировками, то у тебя что-то не так с индексами. Скорее всего нет подходящих индексов для запросов на обновление или наоборот каждое обновление требует обновления слишком большого количества индексов, что замедляет остальные запросы. Тут нужен баланс. Но для начала надо смотреть на гранулдярность блокировок. Слишком частые эскалации блокировок обычно свидетельствуют о хреновых индексах.
4) Статистика. У тебя может быть включено автообновление статистики. Внезапно замедляет работу при крпных объемах. Переведи на ручное обновление по расписанию. Для больших таблиц статистика может быть не очень адекватна. Рецепт лечения тот же.
5) Слишком долго держишь открытый rowset. Как не странно, но часто в прикладном коде встречается ошибка, что обработка результатов запроса делается в цикле, внутри которого происходят тяжелые операции. Люди наверное не думают, что пока rowset открыт база данных может удерживать блокировки. В сочетании с предыдущими проблемами может иметь большой impact.
Если ты сделал все правильно, то ручное управление блокировками тебе понадобится только в одном случае — увеличивать гранулярность блокировки для тяжелых запросов. И то в 1 случае из 1000.
V>Если ты с этими известными сценариями не сталкивался, значит твой опыт с РСУБД весьма однобок.
Сталкивался побольше твоего и успешно решал. И даже заработал хороший гонорар за решение таких проблем
G>>>>Прости, но такого отборного бреда давно не слышал. V>>>На сайтах-магазинах с небольшой нагрузкой и не услышишь. G>>Думаешь база данных знает сайт магазина у тебя или что-то еще?
V>Думаю, что ты с серьёзной нагрузкой никогда не сталкивался. V>Это видно по твоим рассуждениям не только в ответах мне.
Конечно не сталкивался. То что ты считаешь "серьезной нагрузкой" для меня мелочи.
Здравствуйте, gandjustas, Вы писали:
G>В итоге получается что 1С умудряется дичайшее тормозить на совсем скромных объемах.
1С тормозит при активном использовании т.н. "временнЫх данных".
Современные СУБД не заточены под этот специальный вид данных, они хранятся просто как последовательность значений (просто строки в таблицах), например, изменений курсов валют на определённые даты.
Когда такие данные в логике не участвуют, то там быстродействие примерно как везде.
Но речь была именно о хинтах — что там выходит при прочих равных?
Так вот, без хинтов блокировок в запросе всё тормозит еще больше.
V>>Вопрос тут в другом — как продолжить раздавать данные по лёгким частым запросам (пусть единицы тысяч раз в сек) с одновременно выполняющимися тяжелыми нечастыми (пусть их будет десятки/сотни в сек). В твоих "типовых сценариях", т.е. без ручного тюнинга гранулярности блокировок — никак. G> G>У тебя просто потрясающе сочетание тотального профанизма и самомнения.
Судя по написанному ниже, всё с точностью до наоборот.
G>1) Запросы на чтение не мешают друг другу, так как используют исключительно shared блокировки. Если у тебя не так, то ты делаешь какую-то фигню.
Первый приплызд.
Откуда ты вообще взял про "запросы только по чтению", когда я во всём этом топике 100 раз повторял, что специфика по историческим данным (т.е. неизменяемым) и оперативным резко разная?
Итого, сходу начал с борьбы с воображаемым собеседником.
G>2) У тебя выставлены хреновые уровни изоляции.
Откуда ты знаешь какие уровни выставлены?
G>Для типичного приложения чаще всего подходит read commited snapshot в MS SQL.
Садись два.
Бо в этом случае речь о последовательности запросов в одной транзации и к обсуждаемому никаким боком.
Я вообще не сторонник что-то обновлять и затем что-то тяжеловесное запрашивать в рамках одной и той же транзакции, а ты, смотрю, сторонник подобных стрёмных вещей? ))
G>3) Если с уровнями изоляции все в порядке и запросы нормальные, а ты все равно испытываешь проблемы с блокировками, то у тебя что-то не так с индексами. Скорее всего нет подходящих индексов для запросов на обновление или наоборот каждое обновление требует обновления слишком большого количества индексов, что замедляет остальные запросы. Тут нужен баланс.
Единственно с чем соглашусь.
Тут камешек в огород Синклера, который уверяет, что большое кол-во индексов не вредит и предлагает их по 15 шт на таблицу.
Я предлагаю за такое расстреливать.
Но допустим, что схема данных и индексы минимально необходимые (у меня не более 3-4-х индексов для таблиц частообновляемыми данными и сами индексы только по числам и датам).
G>Но для начала надо смотреть на гранулдярность блокировок.
Конечно надо.
G>Слишком частые эскалации блокировок обычно свидетельствуют о хреновых индексах.
Вот тут ты и показал своё профанство, собсно. ))
G>4) Статистика. У тебя может быть включено автообновление статистики.
И я и про это IB и Синклеру говорил, они тоже, типа ржали.
Да, со статистикой надо быть осторожным.
G>Внезапно замедляет работу при крпных объемах.
Но не так сильно, как при столкновении блокировок, т.е. не так сильно сказывается на мгновенных задержках.
Статистика обновляется в фоне.
Хотя да, ресурсы проца жрет.
G>Переведи на ручное обновление по расписанию. Для больших таблиц статистика может быть не очень адекватна. Рецепт лечения тот же.
Для больших таблиц она еще может быть сильно дефрагментирована (т.е. сами индексы могуть сильно дефрагментированы), но это уже отдельная тема и всё-равно, оказывающая не столь катастрофическое влияние, т.е. не в десятки раз по быстродействию уж точно.
G>5) Слишком долго держишь открытый rowset.
С чего ты решил?
Я тут рядом упоминал 8 основных режимов открытия рекордсета и указал самый легковесный из них для случая сервака базы данных и для случая локальной inproc-базы.
G>Как не странно, но часто в прикладном коде встречается ошибка, что обработка результатов запроса делается в цикле, внутри которого происходят тяжелые операции. Люди наверное не думают, что пока rowset открыт база данных может удерживать блокировки.
Опять профанство.
Это зависит от режима открытия рекордсета.
Ты какие режимы сейчас имел ввиду?
К тому же, сразу для енскольких режимов описаное актуально только для относительно большой выборки, подготавливаемой для отправки на клиента.
Т.е. это явно не тот сценарий, бо адекватные разработчики не гонят на клиента тонну данных по результатам запроса.
G>Если ты сделал все правильно, то ручное управление блокировками тебе понадобится только в одном случае — увеличивать гранулярность блокировки для тяжелых запросов. И то в 1 случае из 1000.
Это всё еще детсад, не влияющий кардинально (на пару порядков) на ожидаемое быстродействие.
Всеми этими приседаниями (кроме приписанных мне неверных режимов открытия рекордсета) ты можешь изменить что-то в единицы раз, т.е. мимо.
За счёт более грамотной схемы данных, переформулирования запросов и разнесения данных (в том числе физического по дискам) можно получить порой намного больший выигрыш, но всё-равно будет еще "далеко не то".
V>>Если ты с этими известными сценариями не сталкивался, значит твой опыт с РСУБД весьма однобок. G>Сталкивался побольше твоего и успешно решал. И даже заработал хороший гонорар за решение таких проблем
Ну, решил ты чей-то наколенный затык.
А более единиц сотен запросов в сек. (от силы единиц тысяч, если техника совсем суровая) даже после твоего "решения" там всё-равно не будет.
Это всё "обратная сторона Луны", как я называю подобный срез IT.
Ничего серьёзного с таким подходом не сделаешь.
V>>Думаю, что ты с серьёзной нагрузкой никогда не сталкивался. V>>Это видно по твоим рассуждениям не только в ответах мне. G>Конечно не сталкивался. То что ты считаешь "серьезной нагрузкой" для меня мелочи.
Ну так отзвучь кол-во транзакций в секунду и примерный объем данных?
Здравствуйте, IB, Вы писали:
V>>Ветка на месте, мои ответы на месте. IB>Да, и там хорошо видно, что ни одного ответа по сути добиться от тебя не удалось.
И ты, конечно, можешь показать свои вопросы, на которые не было ответов?
Или слил?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>В итоге получается что 1С умудряется дичайшее тормозить на совсем скромных объемах.
V>1С тормозит при активном использовании т.н. "временнЫх данных". V>Современные СУБД не заточены под этот специальный вид данных, они хранятся просто как последовательность значений (просто строки в таблицах), например, изменений курсов валют на определённые даты. V>Когда такие данные в логике не участвуют, то там быстродействие примерно как везде.
В 1С есть временная метка для записи, джоинить по ней с таблицей курсов не сильно большая проблема.
При этом 1С умудряется тормозить не на аналитических запросах, а на обычных проводках.
V>Но речь была именно о хинтах — что там выходит при прочих равных? V>Так вот, без хинтов блокировок в запросе всё тормозит еще больше.
Если запрос кривой, его можно попытаться ускорить хинтом, но факт кривости запроса не отменяет.
G>>1) Запросы на чтение не мешают друг другу, так как используют исключительно shared блокировки. Если у тебя не так, то ты делаешь какую-то фигню.
V>Первый приплызд. V>Откуда ты вообще взял про "запросы только по чтению", когда я во всём этом топике 100 раз повторял, что специфика по историческим данным (т.е. неизменяемым) и оперативным резко разная? V>Итого, сходу начал с борьбы с воображаемым собеседником.
Так ты сам не сказал какие запросы, я накидываю варианты.
G>>2) У тебя выставлены хреновые уровни изоляции. V>Откуда ты знаешь какие уровни выставлены?
Я предполагаю. С вероятностью близкой к 100% не RCS.
G>>Для типичного приложения чаще всего подходит read commited snapshot в MS SQL. V>Садись два. V>Бо в этом случае речь о последовательности запросов в одной транзации и к обсуждаемому никаким боком.
Ты хочешь сказать что следующий запрос в одной транзакции работает медленнее если предыдущий запрос в той же транзакции навесил много блокировок?
V>Я вообще не сторонник что-то обновлять и затем что-то тяжеловесное запрашивать в рамках одной и той же транзакции, а ты, смотрю, сторонник подобных стрёмных вещей? ))
Похоже что ты разговариваешь с воображаемым собеседником
G>>3) Если с уровнями изоляции все в порядке и запросы нормальные, а ты все равно испытываешь проблемы с блокировками, то у тебя что-то не так с индексами. Скорее всего нет подходящих индексов для запросов на обновление или наоборот каждое обновление требует обновления слишком большого количества индексов, что замедляет остальные запросы. Тут нужен баланс.
V>Единственно с чем соглашусь. V>Тут камешек в огород Синклера, который уверяет, что большое кол-во индексов не вредит и предлагает их по 15 шт на таблицу. V>Я предлагаю за такое расстреливать. V>Но допустим, что схема данных и индексы минимально необходимые (у меня не более 3-4-х индексов для таблиц частообновляемыми данными и сами индексы только по числам и датам).
Пффф. 15 это мало. Я как-то раз ускорил систему в 6 раз сделав почти 50 индексов для таблицы с ~30 колонками.
Тут все зависит от запросов и их частоты.
Делать выводы об индексах на основании из количества — профанизм чистой воды.
G>>Слишком частые эскалации блокировок обычно свидетельствуют о хреновых индексах. V>Вот тут ты и показал своё профанство, собсно. ))
На основании чего ты сделал такой вывод?
Опять профанизм попер?
G>>4) Статистика. У тебя может быть включено автообновление статистики.
V>И я и про это IB и Синклеру говорил, они тоже, типа ржали. V>Да, со статистикой надо быть осторожным.
Нет, ты не это говорил.
G>>Внезапно замедляет работу при крпных объемах.
V>Но не так сильно, как при столкновении блокировок, т.е. не так сильно сказывается на мгновенных задержках. V>Статистика обновляется в фоне. V>Хотя да, ресурсы проца жрет.
Проблема не в этом, а в том, что кривая статистика делает индексы неэффективными. С кривой статистикой даже 3 индекса может быть слишком много.
G>>Переведи на ручное обновление по расписанию. Для больших таблиц статистика может быть не очень адекватна. Рецепт лечения тот же. V>Для больших таблиц она еще может быть сильно дефрагментирована (т.е. сами индексы могуть сильно дефрагментированы), но это уже отдельная тема и всё-равно, оказывающая не столь катастрофическое влияние, т.е. не в десятки раз по быстродействию уж точно.
Может быть ты про фрагментацию? Для данных которые редко удаляются и хороших ключей фрагментация не проблема вообще.
G>>5) Слишком долго держишь открытый rowset. V>С чего ты решил? V>Я тут рядом упоминал 8 основных режимов открытия рекордсета и указал самый легковесный из них для случая сервака базы данных и для случая локальной inproc-базы.
На одном проекте заметил этот эффект. Все в базе было нормально, но блокировки держались сильно дольше, чем ожидалось.
G>>Как не странно, но часто в прикладном коде встречается ошибка, что обработка результатов запроса делается в цикле, внутри которого происходят тяжелые операции. Люди наверное не думают, что пока rowset открыт база данных может удерживать блокировки. V>Опять профанство. V>Это зависит от режима открытия рекордсета. V>Ты какие режимы сейчас имел ввиду?
Я хз, обычный .net-код, который читал из рекордсета. Переписал немного цикл и полетело.
V>К тому же, сразу для енскольких режимов описаное актуально только для относительно большой выборки, подготавливаемой для отправки на клиента. V>Т.е. это явно не тот сценарий, бо адекватные разработчики не гонят на клиента тонну данных по результатам запроса.
Там не была тонна данных, но сочетание тяжеловесного запроса и длительного удержание рекордсета сыграло негативную роль.
Потом код совсем переписали, чтобы запрос был не такой тяжеловесный.
G>>Если ты сделал все правильно, то ручное управление блокировками тебе понадобится только в одном случае — увеличивать гранулярность блокировки для тяжелых запросов. И то в 1 случае из 1000. V>Это всё еще детсад, не влияющий кардинально (на пару порядков) на ожидаемое быстродействие. V>Всеми этими приседаниями (кроме приписанных мне неверных режимов открытия рекордсета) ты можешь изменить что-то в единицы раз, т.е. мимо.
Мимо чего?
V>За счёт более грамотной схемы данных, переформулирования запросов и разнесения данных (в том числе физического по дискам) можно получить порой намного больший выигрыш, но всё-равно будет еще "далеко не то".
Так ты определись уже. Нужна грамотная схема и запросы или хинты блокировок?
Ты же вроде утверждал, что без хинтов получить нормальную скорость невозможно. Уже передумал?
V>>>Если ты с этими известными сценариями не сталкивался, значит твой опыт с РСУБД весьма однобок. G>>Сталкивался побольше твоего и успешно решал. И даже заработал хороший гонорар за решение таких проблем
V>Ну, решил ты чей-то наколенный затык. V>А более единиц сотен запросов в сек. (от силы единиц тысяч, если техника совсем суровая) даже после твоего "решения" там всё-равно не будет.
У меня был кейс где 6 запросов в секунду в пике поднялось до 900, всего-то в 150 раз ускорил.
Люди передумали покупать сервер, который в 10 раз дороже того, который был.
V>Это всё "обратная сторона Луны", как я называю подобный срез IT. V>Ничего серьёзного с таким подходом не сделаешь.
Да-да, один ты у нас занимаешься "серьезными" вещами, что даже фрагментацию от дефрагментации отличить не можешь.
V>>>Думаю, что ты с серьёзной нагрузкой никогда не сталкивался. V>>>Это видно по твоим рассуждениям не только в ответах мне. G>>Конечно не сталкивался. То что ты считаешь "серьезной нагрузкой" для меня мелочи.
V>Ну так отзвучь кол-во транзакций в секунду и примерный объем данных?
2500 запросов в секунду (при тесте) на базе в 100 с чем-то гб. Общий объём таблиц в 30 млн строк с несколькими джоинами.
Тот самый с 50 индексами.
Этого заказчику хватило с запасом в 10 раз.
Здравствуйте, gandjustas, Вы писали:
V>>1С тормозит при активном использовании т.н. "временнЫх данных". V>>Современные СУБД не заточены под этот специальный вид данных, они хранятся просто как последовательность значений (просто строки в таблицах), например, изменений курсов валют на определённые даты. V>>Когда такие данные в логике не участвуют, то там быстродействие примерно как везде. G>В 1С есть временная метка для записи, джоинить по ней с таблицей курсов не сильно большая проблема.
Это если бы курсы были на каждый день, но курс на данную дату нужно вычислять по max(change_date) where change_date<=doc_date.
В этом месте начинаются тормоза.
G>При этом 1С умудряется тормозить не на аналитических запросах, а на обычных проводках.
Смотря на каких. Для "обычной проводки" надо рассчитать сначала все цифры, бо "обычная проводка документа" — это порой до десятка проводок по разным бух.счетам в рамках одной транзакции, вот на этом рассчёте может и тормозить, если сам рассчёт нетривиальный на клиентской стороне.
V>>Но речь была именно о хинтах — что там выходит при прочих равных? V>>Так вот, без хинтов блокировок в запросе всё тормозит еще больше. G>Если запрос кривой, его можно попытаться ускорить хинтом, но факт кривости запроса не отменяет.
Ясно. ))
Похоже, ты не в курсе, зачем хинты вообще нужны.
V>>Ну так отзвучь кол-во транзакций в секунду и примерный объем данных? G>2500 запросов в секунду (при тесте) на базе в 100 с чем-то гб. Общий объём таблиц в 30 млн строк с несколькими джоинами.
Общий объем таблиц не интересен, интересен по которым происходят одновременные/параллельные изменения и выборки.
Бо если из миллионов строк ты постоянно запрашиваешь/изменяешь только десятки тыщ их последних, то не считается.
Мало ли что там на диске хранится.
G>Этого заказчику хватило с запасом в 10 раз.
Ну вот у меня были цифры в 97-м году на однопроцессорном Пентиум-3 500 МГц порядка 180 запросов в секунду для системы учёта предприятия.
В тесте участвуют запросы от эмуляторов "операторов", вводящих новые документы, запросы на проводку/отмену складских документов, запросы по отчетности.
Думаешь, мой нынешний i7-десктоп (даже не сервер, ы-ы-ы) будет работать всего в ~10 раз быстрее?
Еще лет 15 назад на Core-2 Duo тот тест улетел за 20 тыс/с.
Мой нынешний десктоп при такой специфической организации данных и способа работы с ними (которые ты пытался высмеять) даёт сотни тыс запросов/сек.
Здравствуйте, vdimas, Вы писали: V>Это если бы курсы были на каждый день, но курс на данную дату нужно вычислять по max(change_date) where change_date<=doc_date. V>В этом месте начинаются тормоза.
ЕМНИП, именно этот случай мы с MarlboroMan обсасывали на этом сайте году эдак в 2004. Уже тогда MS SQL прекрасно справлялся с такими джойнами.
Вот тут было бы уместно показать определение таблиц, запрос, и его план.
Можно даже без соображений на тему улучшения характеристик запроса (хотя, естественно, client-side join приходит в голову первым).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
V>Это если бы курсы были на каждый день, но курс на данную дату нужно вычислять по max(change_date) where change_date<=doc_date. V>В этом месте начинаются тормоза.
Поиск на == и <= используют один и тот же алгоритм половинного деления по индексу.
Сложность одинакова. Только при курсе на каждый день нужно заполнять все дни (выходные, праздники когда торги не проходят), что увеличивает размер таблицы и индекса
Кроме точного позиционирования, можно производить позиционирование на элемент, ключ которого больше, меньше, больше или равен и меньше или равен некоторому значению. Этим занимается функция Navigate. В качестве параметров она получает значение ключа и тип поиска. Тип поиска задается следующим перечислением:
public
bool Navigate(K Key, NavigateFlag flag)
{
bool result = this.NavigateKey(Key);
// Внутри NavigateKey(Key)
//если не нашли по ключу
// _selected = false;
// Помещаем в _currentElementIndex позицию в которую можно добавить элемент с искомым ключом.
// _currentElementIndex = lo;switch(flag)
{
case NavigateFlag.Eqality :
return result;
case NavigateFlag.GreaterThanOrEqval:
if (result)
return true;
goto case NavigateFlag.GreaterThan;
case NavigateFlag.GreaterThan:
if (result)
_currentElementIndex++;
if (CurrentLeafPage.Count == _currentElementIndex)
{
if (CurrentLeafPage.NextPage == null)
{
_selected = false;
return false;
}
else
{
CurrentLeafPage = CurrentLeafPage.NextPage;
_currentElementIndex = 0;
}
}
_selected = true;
return true;
case NavigateFlag.LessThanOrEqval :
if (result)
returntrue;
goto case NavigateFlag.LessThan;
case NavigateFlag.LessThan:
return this.GetPriorRecord();
}
return result;
}
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, vdimas, Вы писали:
V>Общий объем таблиц не интересен, интересен по которым происходят одновременные/параллельные изменения и выборки. V>Бо если из миллионов строк ты постоянно запрашиваешь/изменяешь только десятки тыщ их последних, то не считается. V>Мало ли что там на диске хранится.
Ну хотя двоичный поиск имеет логарифмическую зависимость, но все таки размер имеет значение.
Система кэширует считанные страницы. И главное это попадание к кэш памяти. Одно дело когда искомые данные закэшированы в памяти
и совсем другое когда надо считывать с диска.
Кстати это было одной из причин когда 1С ники при работе с dbf базами переходили не Цитрих а затем на RDP.
Разница по скорости в десятки раз
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, vdimas, Вы писали:
V>И ты, конечно, можешь показать свои вопросы, на которые не было ответов?
Причем здесь мои вопросы? Как уже многократно отмечалось — чукча не читатель, теряешь нить беседы как отворачиваешься от монитора. =)
Но и мои доступны, ветку пока никто не удалял, перечитай ))
V>Или слил?
Как трогательна твоя робкая надежда, что никому не понятно, что ты слил уже давно, как только перевел разговор в срач.
Здравствуйте, Sinclair, Вы писали:
V>>Это если бы курсы были на каждый день, но курс на данную дату нужно вычислять по max(change_date) where change_date<=doc_date. V>>В этом месте начинаются тормоза. S>ЕМНИП, именно этот случай мы с MarlboroMan обсасывали на этом сайте году эдак в 2004. Уже тогда MS SQL прекрасно справлялся с такими джойнами.
MS SQL справлялся с такими джоинами еще с версии 6.5, т.е. с 96-го года, чем нехило меня удивил.
Бо до этого я наблюдал в других диалектах SQL только джоины по строгому равенству inner, либо outer left/right.
FULL не считается, бо он во многих диалектах получается "сам" и без join.
Собсно, удивило то, что в MS SQL план запроса не зависел от того, использовалась ли для обсуждаемых неординарных соединений конструкция join, или простое where.
Т.е. это уже было дело вкусовщины автора запроса.
Но факт остаётся фактом, такое соединение по групповой операции заметно тяжелее, чем обычный джоин.
S>Вот тут было бы уместно показать определение таблиц, запрос, и его план.
Ничего военного там нет — обычный составной кластерный индекс {код_валюты, дата_изменения_курса}, бо ширина индекса практически равна ширине таблицы.
S>Можно даже без соображений на тему улучшения характеристик запроса (хотя, естественно, client-side join приходит в голову первым).
Часто так и есть.
С т.з. базы запрос де-факто не тяжёлый (вернее, последовательность их не тяжёлая).
Тут используются те прикладные знания, что эти данные неизменяемые, т.е. их можно спокойно посасывать без длиной транзакции на всё время раундтрипа.
Но в целом запрос выполняется пару секунд дольше.
При этом сохраняется высокая степень параллелизма, что архиважно (С) для тупой клиент-серверной архитектуры. ))
В моей системе такие данные не просто посасывались, а еще кешировались в локальной БД, т.е. даже между переподключениями набивать кеши заново не надо было.
Каждый подобный запрос к базе возвращал два рекордсета — первый из них состоял из одной строки, где в колонках были версии соответствующих кешируемых справочников, а второй рекордсет был целевой.
Перед построением на клиенте целевого join со справочниками, у тех проверялись версии относительно пришедших и запрашивались именно строки соотв. справочников, с версией большей, чем соответствующий справочнику номер версии на стороне клиента.
Надеюсь, объяснил не очень сумбурно — каждая строка справочных данных содержит в себе поле version, которое инициализируется при вставке или обновляется при обновлении данных. Т.е. ответная часть логики поддержки клиентского кеша реализована на серваке. поле версии относительно узкое (16 бит), при переполнении поля версии (переходу через 0), поля всех строк версий у справочника сбрасываются, а клиент, обнаружив номер версии, меньшей чем у себя, тоже сбрасывает кеш этого справочника. За 3 года эксплуатации только справочник товаров сделал оборот версии через 0. ))
============
Те "страшные" цифры запросов в сек, что я там приводил — они же малость читерские.
Такие цифры накручиваются за счёт "легких" запросов, но в этом и была цель всех заморачиваний.
В итоге, тяжёлые запросы мешают блокировками только тяжелым запросам, а лёгких на один тяжелый приходится несколько тысяч, вот тебе коэф. "накрутки" быстродействия.
Но без всех этих ухищрений с дефолтным быстродействием 3-5 запросов/сек на одноядерном Пентиум-500 МГц оно просто не жило от слова совсем. ))
Понятно, что уже с середины 2000-х годов быстродействия техники стало хватать для разработки "как по учебнику", но если опять потребуется прыгнуть выше головы даже современной техники — то уже понятно что делать.
Здравствуйте, Serginio1, Вы писали:
S> Поиск на == и <= используют один и тот же алгоритм половинного деления по индексу.
Это при запросе одиночного значения.
При джоинах на индексе этот алгоритм для каждой строчки выполняется не в "чистом" виде, а лишь по интервалу от предыдущего найденного значения (соединяются-то сортированные наборы), т.е. в случае простого join== почти всегда сводится к операции перехода на следующую строку, если текущая строка основного ключа не подошла строке внешнего ключа.
S>Сложность одинакова. Только при курсе на каждый день нужно заполнять все дни (выходные, праздники когда торги не проходят), что увеличивает размер таблицы и индекса
Ну как же одинаковая, если в случае нестрого равенства надо сравнивать даты у двух соседних строчек? ))
Это совсем другой алгоритм перебора строк.
Если первый алгоритм всегда присутствует в базе выполненым на "железячном" уровне, то второй выполняется по классике жанра — через честные параметрические сканы таблиц по индексам и запуски "скриптов" проверки условий (привет метаинформации и всему, что с ней связано), бо таких различных условий, отличных от базовых inner и outer join — их потенциально бесконечный комбинаторный набор.
Здравствуйте, Serginio1, Вы писали:
S> Ну хотя двоичный поиск имеет логарифмическую зависимость, но все таки размер имеет значение. S>Система кэширует считанные страницы. И главное это попадание к кэш памяти.
Верно, в том числе попадание в закешированную область индекса.
О чём и речь.