Я думаю о разработке системы для выполнения высокопараллельных запросов к вложенным (но древовидным) данным. Потенциальные пользователи — аналитики данных (особенно физики), а не программисты. Для пользовательского интерфейса я хочу использовать хорошо известный язык запросов, чтобы избежать распространения новых языков.
Большая часть данных будет структурирована следующим образом (представьте себе следующую схему для миллиардов event
структур):
event: struct
|
+--- timestamp: bigint
+--- missing energy: float
+--- tracks: array of struct
| |
| +--- momentum: float
| +--- theta angle: float
| +--- hits: array of struct
| |
| +--- detector id: int
| +--- charge: float
| +--- time: float
| +--- ...
+--- showers: array of struct
|
+--- ...
База данных будет доступна только для чтения, и большинство запросов будут примерно такими:
- импульс трека с наибольшим количеством хитов с тета от -2,4 до 2,4
- средний заряд всех попаданий со временем в 0-10 пс на всех треках с импульсом более 10 ГэВ/c
- средневзвешенная тета двух треков с наибольшим импульсом
и так далее. Общим для этих запросов является то, что все они разрешаются в один скаляр для каждого события, хотя для этого они углубляются в массивы структур. Они выполняют операции «уменьшения» (обычно fold
в Scala, aggregate
в Spark, DAF в SQL) для отфильтрованных преобразованных подмножеств этих массивов. Я мог бы написать их на Scala так:
// missing check for when zero tracks passed filter!
{event => event.tracks // get list of tracks
.filter(abs(_.theta) < 2.4) // in theta range
.maxBy(_.hits.size) // take the one with the most hits
.momentum // return its momentum
}
{event => mean(
event.tracks // get list of tracks
.filter(_.momentum > 10) // in momentum range
.flatMap(_.hits) // explode to hits
.filter(_.time < 10) // in time range
.map(_.charge) // return their charges
)} // ... to the mean function
// again missing check for less than two tracks!
{event => val List(one, two) = // unpack and assign "one" and "two"
event.tracks // get list of tracks
.sortBy(_.momentum) // sort by momentum
.take(2) // take the first two
// now compute the weighted mean of structs "one" and "two"
(one.theta*one.momentum + two.theta*two.momentum) /
(one.momentum + two.momentum)
}
Почему бы просто не использовать Scala? Моя программа написана на C и будет работать на GPU. Какой бы Scala я ни привнес, это будет перереализованным подмножеством — другими словами, изобретенным языком. (То же самое можно сказать и о Haskell, Javascript или другом языке, который активно использует функции в качестве аргументов.)
Кроме того, эти запросы должны быть декларативными. Если я реализую слишком много языка программирования общего назначения, такие детали, как порядок вызовов функций, могут стать важными.
Почему бы просто не использовать SQL? Можно ли легко писать подобные запросы, чтобы их мог прочитать кто угодно, кроме автора? Запросы, подобные приведенным выше, являются нормой, а не сложными крайностями.
SQL поддерживает вложенные массивы структур, но все примеры использования этой подструктуры, которые я могу найти, ужасно сложны. Нужно разбить таблицу событий на таблицу дорожек (или дважды развернуть, чтобы получить совпадения), и потребуется некоторый сложный учет, чтобы развернуть и вернуться к одному скаляру для каждого события.
Я полагаю, что мог бы использовать SQL с новыми функциями, такими как MAXIMAL(collection, function)
, которые возвращают структуру из массива, подобно track[12]
, но используя предоставленную пользователем функцию в качестве целевой функции для максимизации, минимизации, нахождения максимального/минимального N и т. д. Я не Не думаю, что SQL поддерживает передачу функций в качестве аргументов. Если я напишу SQL, который это делает, это будет нестандартно.
Существует ли широко используемый диалект SQL, поддерживающий передачу функций в качестве аргументов?
Или мне следует рассмотреть другой декларативный язык?
event
таблица с уникальным идентификатором. Затем таблицаtrack
имеет внешний ключ для уникального идентификатора вevent
. Допускает отношения, в которых однаevent
строка связана с от нуля до многихtrack
строк. То же самое относится кevent
:showers
иtrack
:hit
и т. д. и т. д. Затем SQL обычно становится случаем объединения двух таблиц, затем агрегирования, присоединения этого результата к другой таблице и повторного агрегирования и т. д. и т. д. - person MatBailie   schedule 08.08.2016functions as arguments
, это не будет нормальным для любого диалекта SQL. Некоторые из них имеют собственную среду CLR и позволяют делать некоторые волшебные вещи, но даже если вы заставите ее работать, это не будет чем-то, что распознает стандартный разработчик SQL (актуально для вас с точки зрения поддержки) . Но в MS SQL Server естьAPPLY
, который позволяет вам инкапсулировать функции другим способом, который может вам подойти. - person MatBailie   schedule 08.08.2016