Информация об изменениях

Сообщение Re[81]: MS забило на дотнет. Питону - да, сишарпу - нет? от 02.10.2021 9:22

Изменено 02.10.2021 9:47 Sinclair

Re[81]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, vdimas, Вы писали:
V>Зависит от уровня блокировки.
V>Существуют блокировки таблиц/индексов целиком, страниц и отдельных записей.

V>Учитывая, что виды блокировок и их гранулярность находятся в строгой иерархии, я немного не понимаю суть твоих вопросов.

V>Что ты хочешь узнать?
Узнать — ничего. Вот этот вот ликбез, про гранулярность блокировок, который вы мне рассказываете, я преподаю. Вы, кстати, забыли про Update Lock и про Intent блокировки.

Вопрос — в том, как обеспечить быстродействие в реальных задачах, особенно когда планировщик заранее не знает, сколько строк попадёт под предикат.
Превентивный захват блокировок уровня таблицы/индекса сильно снизит concurrency, особенно на многопроцессорных машинах.

S>>На пальцах — цикл сканирования выглядит так:

S>>
S>>foreach(var candidateRow in table.Index1.IndexSeek(predicate.IndexPart))
S>>{
S>>   lock(GetRowLock(candidateRow))
S>>   {
S>>     if(predicate.ResidualPart(candidateRow))
S>>       yield return selector(candidateRow);
S>>   }
S>>}
S>>


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

Такое поведение соответствует уровню блокировки read committed. Если хочется repeatable read — то придётся удерживать локи до конца транзакции.
В данном контексте это непринципиально.

V>В отсутствии конфликтов — одна интерлокед-операция на таблицу для скана таблицы.

V>Считай, бесплатно.
Хм. Я пока не понимаю, как этого можно добиться. Что такое "отсутствие конфликтов"? Открытие базы в монопольном режиме? Так в нём вообще блокировки не нужны.
А если база открыта в немонопольном режиме, то гарантировать отсутствие конкурентных изменений невозможно.

Представим себе, что у нас есть несколько активных транзакций, которые захватили Row-Lock на какие-то строки нашей таблицы.
Вот у нас начинается table scan. Вы, если я правильно понял, предлагаете захватить table lock. Как это будет сделано?
Сдаётся мне, что одной интерлокед-операцией обойтись не удастся.
В общем, тут у меня некоторый пробел — я не вижу способа сделать захват блокировок шибко эффективным.

V>Разве такое положение вещей не наводит на необходимые мысли?

Наводит. Я в направлении этих мыслей работаю.

V>План запроса в любом случае оперирует готовыми предкомпилёнными "кубиками".

V>Речь о грануляции этих "кубиков".
Ну, в существующих СУБД план запроса оперирует интерпретацией выражений. В "кубик" вставляется некоторый код, который подходит только для одного конкретного плана конкретного запроса.
Как собрать эффективный план из предкомпилированных кусков — большой вопрос.

S>>Это сильно ухудшает производительность сканирования — вместо тупого обращения по смещению pageNo*pageSize, нужно лезть в bufferManager.getPage(pageNo), который даже на happy path добавляет лишнюю косвенность.


V>Косвенность на страницу и косвенность на поле — немного разные вещи.

V>Косвенность на страницу "размазывается" на стоимость обработки многих хранящихся на странице записей.
Возможно. Надо смотреть. Опять же — сильно зависит от типов данных и ширины таблиц. Узкие таблицы с арифметикой — да, всё ок. Широкие таблицы с текстом — там для сборки одной записи может потребоваться прыгать по страницам.

V>Мой подход в первейшую очередь отталкивается от того, что трафик чтения серьезно превалирует над трафиком записи, бо в случае записи в базу компиляция всего и вся в суровый нейти не даст порядка прироста производительности. Просто при записи чаще всего происходит обязательное сначала чтение-поиск (в т.ч. при проверке целостности уникальных индексов/ключей), это надо держать в голове. ))

Эмм, то есть ваш подход полезен только для определённого профиля задач.

V>А общую эффективность в многопользовательской среде поднимает в квадрат раз от этой константы.

Не совсем так Константа же вычитается, а не делит время.

V>Т.е., "законный" O(log(N)) будет при отсутствии всякой статистики.

Не, статистика не поможет вам выехать из O(log(N)). Она работает не так. Точнее, есть один тип индексов, построенный на знании об "островках" данных, но его придумали вот только пару лет тому, и ни в одной СУБД пока промышленно он не применяется. А о применении такой статистики, как вы говорите, в B/B+/B* деревьях я никогда не слышал.
Ъто интересно, если работает — пришлите ссылку на описание подхода.

V>"Самописные" базы показывали ускорение на пару порядков еще в первой половине 90-х.

V>Такие базы писались для неконкурентного чтения-записи, обслуживались заведомо предкомпилённым кодом, т.е. АПИ такой базы давало заранее известный набор обслуживаемых запросов.
Совершенно верно. А ещё они клали болт на fault tolerance и ограничения целостности. Так-то кто угодно может.
Понятно, что даже банальное чтение несжатого .csv из файла положит на лопатки любую СУБД.

V>Я тщательно крутил одну из тогдашних бухгалтерий на DOS (текстовое "оконное" приложение) с собственным неконкурентным компиллируемым движком БД — с тогдашними СУБД на той технике сравнивать было бесполезно. Эта бухгалтерия была входу в нашем городе примерно до 95-96-х годов (вот этот человек автор, тогда 30+ ему было: https://companies.rbc.ru/id/1149204047024-ooo-irbis/, считался гением IT в нашем городе, занимался нацчными исследованиями в области IT, пока не ушел из ВУЗ-а), в общем, оно было востребовано пока 1С не начала пожирать всех, да и вообще, пока Windows окончательно не вытеснила DOS.

Кто из них — Абрамов или Пустовойтенко?
А так-то — плох тот программист, который не писал свою бухгалтерию на DOS.

V>Пока мест JIT-компиляция работает не на таком уровне, а движки баз данных не генерят код, пригодный для JIT.

Генерят. Можно посмотреть на MemSQL с одного конца, и на Natively Compiled Stored Procedures в SQL Server — с другого.
Re[81]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, vdimas, Вы писали:
V>Зависит от уровня блокировки.
V>Существуют блокировки таблиц/индексов целиком, страниц и отдельных записей.

V>Учитывая, что виды блокировок и их гранулярность находятся в строгой иерархии, я немного не понимаю суть твоих вопросов.

V>Что ты хочешь узнать?
Узнать — ничего. Вот этот вот ликбез, про гранулярность блокировок, который вы мне рассказываете, я преподаю. Вы, кстати, забыли про Update Lock и про Intent блокировки.

Вопрос — в том, как обеспечить быстродействие в реальных задачах, особенно когда планировщик заранее не знает, сколько строк попадёт под предикат.
Превентивный захват блокировок уровня таблицы/индекса сильно снизит concurrency, особенно на многопроцессорных машинах.

S>>На пальцах — цикл сканирования выглядит так:

S>>
S>>foreach(var candidateRow in table.Index1.IndexSeek(predicate.IndexPart))
S>>{
S>>   lock(GetRowLock(candidateRow))
S>>   {
S>>     if(predicate.ResidualPart(candidateRow))
S>>       yield return selector(candidateRow);
S>>   }
S>>}
S>>


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

Такое поведение соответствует уровню блокировки read committed. Если хочется repeatable read — то придётся удерживать локи до конца транзакции.
В данном контексте это непринципиально.

V>В отсутствии конфликтов — одна интерлокед-операция на таблицу для скана таблицы.

V>Считай, бесплатно.
Хм. Я пока не понимаю, как этого можно добиться. Что такое "отсутствие конфликтов"? Открытие базы в монопольном режиме? Так в нём вообще блокировки не нужны.
А если база открыта в немонопольном режиме, то гарантировать отсутствие конкурентных изменений невозможно.

Представим себе, что у нас есть несколько активных транзакций, которые захватили Row-Lock на какие-то строки нашей таблицы.
Вот у нас начинается scan этой таблицы в ещё одной транзакции. Вы, если я правильно понял, предлагаете захватить table lock. Как это будет сделано?
Сдаётся мне, что одной интерлокед-операцией обойтись не удастся.
В общем, тут у меня некоторый пробел — я не вижу способа сделать захват блокировок шибко эффективным.

V>Разве такое положение вещей не наводит на необходимые мысли?

Наводит. Я в направлении этих мыслей работаю.

V>План запроса в любом случае оперирует готовыми предкомпилёнными "кубиками".

V>Речь о грануляции этих "кубиков".
Ну, в существующих СУБД план запроса оперирует интерпретацией выражений. В "кубик" вставляется некоторый код, который подходит только для одного конкретного плана конкретного запроса.
Как собрать эффективный план из предкомпилированных кусков — большой вопрос.

S>>Это сильно ухудшает производительность сканирования — вместо тупого обращения по смещению pageNo*pageSize, нужно лезть в bufferManager.getPage(pageNo), который даже на happy path добавляет лишнюю косвенность.


V>Косвенность на страницу и косвенность на поле — немного разные вещи.

V>Косвенность на страницу "размазывается" на стоимость обработки многих хранящихся на странице записей.
Возможно. Надо смотреть. Опять же — сильно зависит от типов данных и ширины таблиц. Узкие таблицы с арифметикой — да, всё ок. Широкие таблицы с текстом — там для сборки одной записи может потребоваться прыгать по страницам.

V>Мой подход в первейшую очередь отталкивается от того, что трафик чтения серьезно превалирует над трафиком записи, бо в случае записи в базу компиляция всего и вся в суровый нейти не даст порядка прироста производительности. Просто при записи чаще всего происходит обязательное сначала чтение-поиск (в т.ч. при проверке целостности уникальных индексов/ключей), это надо держать в голове. ))

Эмм, то есть ваш подход полезен только для определённого профиля задач.

V>А общую эффективность в многопользовательской среде поднимает в квадрат раз от этой константы.

Не совсем так Константа же вычитается, а не делит время.

V>Т.е., "законный" O(log(N)) будет при отсутствии всякой статистики.

Не, статистика не поможет вам выехать из O(log(N)). Она работает не так. Точнее, есть один тип индексов, построенный на знании об "островках" данных, но его придумали вот только пару лет тому, и ни в одной СУБД пока промышленно он не применяется. А о применении такой статистики, как вы говорите, в B/B+/B* деревьях я никогда не слышал.
Ъто интересно, если работает — пришлите ссылку на описание подхода.

V>"Самописные" базы показывали ускорение на пару порядков еще в первой половине 90-х.

V>Такие базы писались для неконкурентного чтения-записи, обслуживались заведомо предкомпилённым кодом, т.е. АПИ такой базы давало заранее известный набор обслуживаемых запросов.
Совершенно верно. А ещё они клали болт на fault tolerance и ограничения целостности. Так-то кто угодно может.
Понятно, что даже банальное чтение несжатого .csv из файла положит на лопатки любую СУБД.

V>Я тщательно крутил одну из тогдашних бухгалтерий на DOS (текстовое "оконное" приложение) с собственным неконкурентным компиллируемым движком БД — с тогдашними СУБД на той технике сравнивать было бесполезно. Эта бухгалтерия была входу в нашем городе примерно до 95-96-х годов (вот этот человек автор, тогда 30+ ему было: https://companies.rbc.ru/id/1149204047024-ooo-irbis/, считался гением IT в нашем городе, занимался нацчными исследованиями в области IT, пока не ушел из ВУЗ-а), в общем, оно было востребовано пока 1С не начала пожирать всех, да и вообще, пока Windows окончательно не вытеснила DOS.

Кто из них — Абрамов или Пустовойтенко?
А так-то — плох тот программист, который не писал свою бухгалтерию на DOS.

V>Пока мест JIT-компиляция работает не на таком уровне, а движки баз данных не генерят код, пригодный для JIT.

Генерят. Можно посмотреть на MemSQL с одного конца, и на Natively Compiled Stored Procedures в SQL Server — с другого.