LINUX.ORG.RU

Декларативность SQL, как от нее избавиться.

 ,


0

3

Задача: есть таблица с данными (много),

table {
  id,
  category
  value,
  time
}

время не упорядоченно, т.е. возможны ситуации когда [N+1].time < [N].time

данные нужно:

1 отфильтровать в виде «category in (1...N)» и в диапазоне времени

2 найти пары записей между которыми значение value пересекает некую границу.

3 сгруппировать данные по категориям и отсортировать по времени

Внимание, фокус! Оптимальный алгоритм работы на sql не реализуем, а у планировщиков запросов субд свое мнение на этот счет (особенно отсортировать в середине раз десять), а ведь задача решается в один проход + сортировка резульатата

И тут все в белом NoSQL системы где mapreduce и тупые империативные или функциональные запросы 8(

Deleted

мб вам стоит посмотреть что такое оконные функции? Если хочется именно СУБД и SQL

mashina ★★★★★
()

И тут все в белом NoSQL системы где mapreduce и тупые империативные или функциональные запросы 8(

И что тебе мешает сделать SELECT * FROM whatever, а потом «решить задачу простым циклом»?

tailgunner ★★★★★
()
Ответ на: комментарий от KRoN73

дык, в sql циклы есть только в процедурах, но процедуры это не вариант.

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

Deleted
()
Ответ на: комментарий от tailgunner

так база и ПО на одной машине, но понять в память 10гиг, переколбасить в доступный для яп вид, затем выкинуть 99% - что-то тут не так, там проседание на IO и преобразовании типов то бешоное. А так у субд есть индексы по value, и тоеретически можно было бы на их анализе это 90% не трогать

Deleted
()
Ответ на: комментарий от Deleted

для задачи решающейся простым циклом?

это, мягко говоря, не совсем так. Простой цикл там только первый и второй пункты, у обычного SQLя будут проблемы со вторым, для этого как раз предлагал посмотреть на оконные функции.

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

Нет, конечно, можно обойти все 10гб один раз, наплодив ещё несколько обходов и/или куч на диске, и сказать что типа вот был всего один простой цикл.

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от Deleted

То есть настоящий вопрос звучит как «чото у меня не то происходит» и не имеет отношения ни к декларативности, ни к NoSQL.

tailgunner ★★★★★
()
Ответ на: комментарий от mashina

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

Субд его делает перед вторым шагом, просто потому что время не упорядоченно, по факту же там вероятность того что время будет перепутано меньше процента, т.е. буфера в памяти хватит, но база то этого не знает!

Далее сам фокус «следующая запись» в субд - это подзапрос (с сортировкой по времени и последующим limit 1), со всеми вытекающими.

а выходных данных столь мало что группировка поместится в памяти опятьже - т.е. с точки зрения прикладного программиста это распихивание в какойнить словарь (понятно что внутри словаря цыклы, но это вам не монстр group by).

Deleted
()
Ответ на: комментарий от Deleted

Хвостострел, перечитай пост mashina

И? У него почему-то время не упорядочено. 'Отфильтровать в виде «category in (1...N)» и в диапазоне времени' - это один проход при наличии индексов по категории и времени; если этих индексов нет - чего ты ждешь?

tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

а выходных данных столь мало что группировка поместится в памяти опятьже - т.е. с точки зрения прикладного программиста это распихивание в какойнить словарь (понятно что внутри словаря цыклы, но это вам не монстр group by)

нет, это не словарь, а словарь + heap или уже отсортированный список. И это ровно тоже самое, что и group by, что и mapreduce.

mashina ★★★★★
()
Ответ на: комментарий от Deleted

Ну хорошо, еще индекс по value. SELECT id FROM table WHERE value < X ORDER BY value DESC LIMIT 1, SELECT id FROM table WHERE value >= X ORDER BY value DESC LIMIT 1. Правда, атомарно это сделать не получается.

note173 ★★★★★
()

Вот как примерно можно решить второй пункт через оконные ф-ии (линк на доку к PG 1 и 2)

SELECT A, B FROM(
   SELECT value as A, lag(value, 1) as B 
         OVER(ORDER BY ID)
         FROM table)
      WHERE A <= border AND B > border

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от Deleted

так база и ПО на одной машине

Жостко. Вспоминается зайказчег с госконторки... АРМ какого-то реестра ценных бумаг... 1 АРМ - 1 MS SQL 2008 R2. (Нафига?) Весь АРМ - тонкая прослойка формачек, обмазанных в неожиданных местах несвежим T-SQL(которому «Т» где-то по дороге сладострастно отломили простыми циклами по таблицам) с неочевидными ходами взад-вперед в триггеры за блобами любовно сохраненных в базу формочек и огромных простыней «представлений»... любовно продублированных хардкодом в неожиданных местах... Предлагали переделать... разраб кивает на тестера, тестер на аналитика... аналитик выдает «никто на это не пойдет. Впилите по-быстрому согласно ТЗ» (в ТЗ адЪ и шизофазия)

slackwarrior ★★★★★
()

Ящитаю, что вбросы вида «смотрите, на Х получается говно, я на Y сделал бы в сто тыщ раз пиздатей и по феншую» надо нещадно удалять.

staseg ★★★★★
()
Ответ на: комментарий от Deleted

А так у субд есть индексы по value, и тоеретически можно было бы на их анализе это 90% не трогать

Тут нужны индексы

Index1. category,time Index2. value

Задача №2 в описанном ТЗ решения вообще не имеет хоть в SQL хоть в NoSQL - ибо указания что записей с различающимся value на значение delta точно стопудово пара, а не скажем тройка, четверка и т.д. не наблюдается.

Прежде чем сетовать на «монстра group by» - нужно посмотреть планы запросов на хотя бы нескольких разных СУБД. А то ненароком окажется что монстр появляется исключительно на используемой, кстати так и не названной СУБД

anonymous
()

а эти три пункта - это три разных запроса, или все 3 пункта нужно выполнить одним запросом?

Harald ★★★★★
()

1 отфильтровать в виде «category in (1...N)» и в диапазоне времени

нужны индексы по времени и id

2 найти пары записей между которыми значение value пересекает некую границу.

и ещё по value

3 сгруппировать данные по категориям и отсортировать по времени

ну и по категориям...

Внимание, фокус! Оптимальный алгоритм работы на sql не реализуем, а у планировщиков запросов субд свое мнение на этот счет (особенно отсортировать в середине раз десять), а ведь задача решается в один проход + сортировка резульатата

не понимаю - если есть эти индексы, то будет 0 проходов. Время будет O(log(N)). Или в NoSQL какое-то неправильное SQL?

drBatty ★★
()
Ответ на: комментарий от anonymous

Задача №2 в описанном ТЗ решения вообще не имеет хоть в SQL хоть в NoSQL - ибо указания что записей с различающимся value на значение delta точно стопудово пара, а не скажем тройка, четверка и т.д. не наблюдается.

если id уникальный, то id и id+1 точно будет ПАРА. Или там будет 1 или 0 строк. Но если id идут подряд, то всегда будут пары, кроме последней строки.

кстати так и не названной СУБД

в тегах NoSQL.

drBatty ★★
()
Ответ на: комментарий от drBatty

если id уникальный, то id и id+1 точно будет ПАРА.

У которых вполне может не выполняется условие перехода value через некую границу,зато оно может выполняться у id+2 и id-10. Так что замечание странное и не в тему. id вообще не обязан быть целым положительным автоинкриментом, особенно в NoSQL системах

в тегах NoSQL.

Спасибо КЭП. 1. В названии топика Декларативность SQL 2. NoSQL часто расшифровывается как Not only SQL 3. СУБД >= РСУБД, и даже СУБД >= NoSQL СУБД

anonymous
()

найти пары записей между которыми значение value пересекает некую границу.

Критерий «пары» в студию

сгруппировать данные по категориям и отсортировать по времени

Сам то хоть понял что сказал? Либо говоришь «сгруппировать по категории», либо «отсортировать по категории, внутри одинаковых категорий сортировать по имени»

Если все NoSQL-адепты так «ставят задачу», то судьбу NoSQL можно угадать без раздумий - утонет в г..не своих адептов.

no-dashi ★★★★★
()
Ответ на: комментарий от anonymous

У которых вполне может не выполняется условие перехода value через некую границу,зато оно может выполняться у id+2 и id-10. Так что замечание странное и не в тему.

я думал «пара строк», это когда строки соседние. Например 9000 и 9001.

id вообще не обязан быть целым положительным автоинкриментом, особенно в NoSQL системах

я понимаю, что id не обязан быть целым, но почему именно в NoSQL (я не троллю, я с NoSQL не сталкивался IRL, потому не в курсе).

Спасибо КЭП. 1. В названии топика Декларативность SQL 2. NoSQL часто расшифровывается как Not only SQL 3. СУБД >= РСУБД, и даже СУБД >= NoSQL СУБД

повторяю: я не в курсе этого вопроса.

drBatty ★★
()
Ответ на: комментарий от drBatty

я думал «пара строк», это когда строки соседние. Например 9000 и 9001.

Первый пост, вопрос номер два. А то получилось классическое: топик не читал, сразу отвечал

anonymous
()
Ответ на: комментарий от anonymous

Задача №2 в описанном ТЗ решения вообще не имеет хоть в SQL хоть в NoSQL - ибо указания что записей с различающимся value на значение delta точно стопудово пара, а не скажем тройка, четверка и т.д. не наблюдается.

Если бы та прочитало внимательно то узнало, что фразу «что записей с различающимся value на значение delta точно стопудово пара» ты выдумало само, а в оригинале «пара значений между которыми пересекается граница» - это всегда будет пара, даже если одно из значений совпадает с границей и дублируется.

Deleted
()
Ответ на: комментарий от drBatty

2 найти пары записей между которыми значение value пересекает некую границу.

и ещё по value

на практике такая индексация головного мозга приводт к 140гб индексов и 40 гб собственно данных, и на IO все ложится.

Deleted
()
Ответ на: комментарий от mashina

функция lag - читерство чистейшей воды, но теоретически задачу решит (надо на живой базе проверить), только order by time

Deleted
()
Ответ на: комментарий от den73

тем что - хранимые процедуры классический признак больной архитектуры.

Логика должна быть в одном месте, а хранение данных в другом, а запихивание логики в субд - смертный грех программиста.

Deleted
()
Ответ на: комментарий от Deleted

Логика должна быть в одном месте, а хранение данных в другом

Так сказал Господь Бог или кто?

den73 ★★★★★
()
Ответ на: комментарий от Deleted

Логика должна быть в одном месте, а хранение данных в другом

Так сказал Господь Бог или кто?

den73 ★★★★★
()
Ответ на: комментарий от mashina

Глупый и опасный стереотип это размазывать логику как сопли. Хотя если ты создаешь софт по принципу «написал и забыл» то вполне себе практичный.

Deleted
()
Ответ на: комментарий от Deleted

это всегда будет пара, даже если одно из значений совпадает с границей и дублируется.

Увы NoSQL бред, основанный не чем то невысказанном.

Вот тебе пример

id=1 value=10
id=2 value=10
id=3 value=30

Представим что граница это value=20 - тогда получаем ДВЕ абсолютно корректные ПАРЫ (1-3) и (2-3).

Способ выбора пары в ТЗ не описан, в декларативном SQL выбор пары будет обусловлен кучей как внешних (текст запроса), так и внутренних (индексы, статистика, особенность планировщика) свойств.

И даже если взять твоё предложение - аля мотаем цикл и сортируем выбранное - пары будут разные, в зависимости от направления цикла - прямое или обратное.

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

anonymous
()
Ответ на: комментарий от Deleted

Как же все боятся перечить этим больным людям со стереотипами вроде «убью за гоуту» и «порежу за хп»...

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

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

anonymous
()

Если я правильно понял вторую задачу, то её «императивное» решение требует не одного прохода, а двух вложенных циклов.

На SQL то же самое делается селф-джойном, как-то так:

SELECT t1.id pair1_id, t2.id pair2_id
FROM your_table t1 INNER JOIN your_table t2
ON %THRESHOLD% BETWEEN t1.value AND t2.value

где %THRESHOLD% — пороговое значение.

Или под парами понимаются идущие подряд строки? Это тоже можно сделать джойном, но несколько сложнее.

Apple-ch ★★
()

И тут все в белом NoSQL системы где mapreduce и тупые империативные или функциональные запросы 8(

mapreduce это там где N отдельных узлов выполняющих запросы параллельно ? Ну ну

anonymous
()
Ответ на: комментарий от Deleted

на практике такая индексация головного мозга приводт к 140гб индексов и 40 гб собственно данных, и на IO все ложится.

да. Но без индексов тебе придётся перебирать ВСЕ строки по очереди, в поисках нужных. Я не очень понимаю, зачем тебе тогда СУБД? Запиши всё в файл, и перебирай(как ты говоришь «простым циклом») - будет также «быстро», и также экономично. Если хочешь быстрее - делай индексы. Без этого никак.

Пойми простую вещь: индекс ускоряет обработку за счёт дополнительного использования памяти. Чудес не бывает.

drBatty ★★
()
Ответ на: комментарий от mashina

Логика должна быть в одном месте, а хранение данных в другом

чушь и глупый стериотип (паттерн)

не. Смысл в этом правиле есть, оно нужное и годное. Но это конечно не догмат.

drBatty ★★
()
Ответ на: комментарий от anonymous

Написал бы хп и шел дальше

ИМХО хп тут тормозить будет жутко. Впрочем - пусть ТС пробует, я понял условие на 55%.

drBatty ★★
()
Ответ на: комментарий от anonymous

Представим что граница это value=20 - тогда получаем ДВЕ абсолютно корректные ПАРЫ (1-3) и (2-3).

Это шизофрения, а корректная только 2-3, попробуй догадаться почему.

Deleted
()
Ответ на: комментарий от Apple-ch

На SQL то же самое делается селф-джойном, как-то так:

не делается, запрос который ты записал выведет некую ересь, а надо запись до границы и аналогичную ей запись после, т.е. там будет условие:

t1.category = t2.category and 
t2.time = (select min(time) from your_table where time > t1.time and t1.category = t2.category)

и при этом надо сохранить условие того что t2.value обязательно будет больше границы.

Deleted
()
Ответ на: комментарий от drBatty

да. Но без индексов тебе придётся перебирать ВСЕ строки по очереди

Ай яй яй, b-tree оптимизируется для минимизации обращений к диску, создавая кучу распухших индексов которые используются одновременно ты породишь то самое от чего пытались избавиться, причем что характерно обращения будут непоследовательные.

таким макаром последовательно чтение файла может оказаться быстрее, именно если уложиться в один проход чтения.

Deleted
()
Ответ на: комментарий от Deleted

Надо чётче формулировать условия, носкульщик ты наш. Итак, что такое «пара» в твоём случае? В частности, откуда ты высосал условие для time в своём примере?

Apple-ch ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.