- PVSM.RU - https://www.pvsm.ru -
Рассказываю из личного опыта, что где и когда пригодилось. Обзорно и тезисно, чтобы понятно было, что и куда можно копать дальше — но тут у меня исключительно субъективный личный опыт, у вас, может быть, все совсем по-другому.
Почему важно знать и уметь обращаться с языками запросов? По своей сути в Data Science есть несколько важнейших этапов работы и самый первый и важнейший (без него уж точно ничего работать не будет!) — это получение или извлечение данных. Чаще всего данные в каком-то виде где-то сидят и их нужно оттуда «достать».
Языки запросов как раз и позволяют эти самые данные извлечь! И сегодня я расскажу, о тех языках запросов, которые мне пригодились и расскажу-покажу, где и как именно — зачем оно нужно для изучения.
Всего будет три основных блока типов запросов к данным, которые мы разберем в данной статье:
Все написанное здесь — это просто персональный опыт, что пригодилось, с описанием ситуаций и «зачем оно было нужно» — каждый может примерить, насколько подобные ситуации могут встретиться вам и попробовать подготовиться к ним заранее, разобравшись с этими языками до того, как придется их в (срочном порядке) применять на проекте или вообще попасть на проект, где они нужны.
Стандартные языки запросов именно в том плане, что обычно мы именно о них и думаем, когда говорим про запросы.
Зачем сегодня нужна реляционная алгебра? Для того чтобы иметь хорошее представление, почему языки запросов устроены определенным образом и осознанно их использовать нужно разобраться с ядром, лежащим в основе.
Что такое реляционная алгебра?
Формальное определение такое: реляционная алгебра -- замкнутая система операций над отношениями в реляционной модели данных. Если чуть более по-человечески, это система операций над таблицами, такая что результатом тоже всегда является таблица.
См. все реляционные операции в этой [1] статье с Хабра — здесь же мы описываем, зачем нужно знать и где пригождается.
Зачем?
Начинаешь понимать, на что вообще складываются языки запросов и какие операции стоят за выражениями конкретных языков запросов — часто дает более глубокое понимание того, что и как работает в языках запросов.
Взято из этой [1] статьи. Пример операции: join, который объединяет таблицы.
Материалы для изучения:
Хороший вводный курс от Стэнфорда [2]. Вообще, материалов по реляционной алгебре и теории очень много — Сoursera, Udacity. Есть также огромное количество материалов онлайн, в том числе хороших академических курсов [3]. Мой персональный совет: надо понимать реляционную алгебру очень хорошо — это основа основ.
Взято из этой [1] статьи.
SQL — это, по сути, имплементация реляционной алгебры — с важной оговоркой, SQL — декларативен! То есть записывая запрос на языке реляционной алгебры, вы фактически говорите, как нужно считать — а вот с SQL вы задаете, что хотите извлечь, а дальше СУБД уже генерирует (эффективное) выражения на языке реляционной алгебры (их эквивалентность известна нам под теоремой Кодда [4]).
Взято из этой [1] статьи.
Зачем?
Реляционные СУБД: Oracle, Postgres, SQL Server, etc — по-прежнему фактически повсюду и невероятно велик шанс того, что вам придется с ними взаимодействовать, а это означает, что придется либо читать SQL (что очень вероятно), либо писать на нем (тоже не маловероятно).
Что читать и изучать
По тем же ссылкам выше (про реляционную алгебру), есть невероятное количество материала, например, этот [5].
Кстати, а что такое NoSQL?
«Стоит еще раз подчеркнуть, что термин «NoSQL» имеет абсолютно стихийное происхождение и не имеет общепризнанного определения или научного учреждения за спиной.» Соответствующая статья [6] на Хабре.
По сути, люди поняли, что полная реляционная модель не нужна для решения многих задач, особенно для тех, где, например, принципиальна производительность и доминируют определенные простые запросы с агрегацией — там критично быстро считать метрики и писать их в базу, а большинство фич реляционной оказались не только не нужны, но и вредны — зачем нормализовывать что-то, если это будет портить самое важное для нас (для некоторой конкретной задачи) — производительность?
Также часто нужные гибкие схемы вместо фиксированных математических схем классической реляционной модели — и это невероятно упрощает разработку приложений, когда критично развернуть систему и начать работать быстро, обрабатывая результаты — или схема и типы хранимых данных не так уж и важны.
Например, мы создаем экспертную систему и хотим хранить информацию по определенному домену вместе с некоторой метаинформацией — мы можем и не знать всех полей и банально хранить JSON для каждой записи — это дает нам очень гибкую среду для расширения модели данных и быстрого итерирования — поэтому в таком случае NoSQL будет даже предпочтительнее и читаемее. Пример записи (из одного моего проекта, где NoSQL был прям там, где нужно).
{"en_wikipedia_url":"https://en.wikipedia.org/wiki/Johnny_Cash",
"ru_wikipedia_url":"https://ru.wikipedia.org/wiki/?curid=301643",
"ru_wiki_pagecount":149616,
"entity":[42775,"Джонни Кэш","ru"],
"en_wiki_pagecount":2338861}
Подробнее можно прочитать тут [7] про NoSQL.
Что изучать?
Тут скорее нужно быть просто хорошо проанализировать свою задачу, какие у нее свойства и какие имеются NoSQL системы, который бы подходили под это описание — и уже заниматься изучением данной системы.
Сначала, кажется, причем тут вообще Python — это язык программирования, а не про запросы вовсе.
Мой главный совет: учите Python!
Возьмем в качестве примера следующий код:
import pandas as pd
df = pd.read_csv(“data/dataset.csv”)
# Calculate and rename aggregations
all_together = (df[df[‘trip_type’] == “return”]
.groupby(['start_station_name','end_station_name'])
.agg({'trip_duration_seconds': [np.size, np.mean, np.min, np.max]})
.rename(columns={'size': 'num_trips',
'mean': 'avg_duration_seconds',
'amin': min_duration_seconds',
‘amax': 'max_duration_seconds'}))
По сути, мы видим, что код вписывается в классический SQL паттерн.
SELECT start_station_name, end_station_name, count(trip_duration_seconds) as size, …..
FROM dataset
WHERE trip_type = ‘return’
GROUPBY start_station_name, end_station_name
Но важная часть — этот код является часть скрипта и пайплайна, фактически мы встраиваем запросы в Питоновский пайплайн. В данной ситуации язык запросов к нам приходит из библиотек, таких как Pandas или pySpark.
В целом в pySpark мы видим схожий тип трансформации данных через язык запросов в духе:
df.filter(df.trip_type = “return”)
.groupby(“day”)
.agg({duration: 'mean'})
.sort()
Где и что почитать
По самому питону вообще не проблема [8] найти материалы для изучения. В сети огромное количество тьюториалов по pandas [9], pySpark [10] и курсов по Spark [11] (а также по самому DS [12]). В целом тут материалы великолепно гуглятся и если бы мне нужно было выбрать один пакет, на котором стоит сфокусироваться — то это был бы pandas, конечно. По связке DS+Python материалов тоже очень много [13].
Немало проектов по обработке и анализу данных, с которыми мне приходилось работать — это, по сути, shell скрипты, которые вызывают код на питоне, на java и собственно сами shell команды. Поэтому в целом можно рассматривать пайплайны в баше/zsh/etc, как некоторый высокоуровневый запрос (можно туда, конечно, и циклы запихать, но это нетипично для DS кода на шелл языках), приведем простой пример — мне нужно было сделать маппинг QID викидаты и полной ссылки на русскую и английскую вики, для этого я написал простой запрос из команд в баше и для вывода написал простой скприт на питоне, которые я собрал вместе вот так:
pv “data/latest-all.json.gz” |
unpigz -c |
jq --stream $JQ_QUERY |
python3 scripts/post_process.py "output.csv"
где
JQ_QUERY = 'select((.[0][1] == "sitelinks" and (.[0][2]=="enwiki" or .[0][2] =="ruwiki") and .[0][3] =="title") or .[0][1] == "id")'
Это был, по сути, весь пайплайн, который создавал нужный mapping, как мы видим все, работало в режиме потока:
Итого сложный пайплайн работающий в режиме потока на больших данных (0.5TB), без существенных ресурсов и сделан из простого пайплайна и пары тулзов.
Еще один важный совет: умейте хорошо и эффективно работать в терминале и писать на bash/zsh/etc.
Где пригодится? Да почти везде — материалов для изучения опять же ОЧЕНЬ много в сети. В частности, вот эта [14] моя предыдущая статья.
Опять же читатель может воскликнуть — ну это же целый язык программирования! И конечно же, будет прав. Однако, обычно мне приходилось сталкиваться с R всегда в таком контексте, что, по сути, это было очень похоже на язык запросов.
R — это среда статистических вычислений и язык статических вычислений и визуализации (согласно этому [15]).
Взято отсюда [16]. Кстати, рекомендую, неплохой материал.
Зачем дата саентисту знать R? По крайней мере, потому что есть огромный пласт людей не из IT, которые занимаются анализом данных на R. Мне встречалось в следующих местах:
Почему это фактически язык запросов? В том виде, в котором он часто встречается — это фактически запрос на создание модели, включая чтение данных и фиксирование параметров запроса (модели), а также визуализация данных в таких пакетах как ggplot2 — это тоже форма написания запросов.
Пример запросов для визуализации
ggplot(data = beav,
aes(x = id, y = temp,
group = activ, color = activ)) +
geom_line() +
geom_point() +
scale_color_manual(values = c("red", "blue"))
В целом многие идеи из R перекочевали в пакеты python, такие как pandas, numpy или scipy, как датафреймы и векторизация данных — поэтому в целом очень многие вещи в R покажутся вам знакомыми и удобными.
Источников для изучения много, например, этот [17].
Тут у меня чуть необычный опыт, потому что мне таки довольно часто приходится работать с графами знаний и языки запросов к графам. Поэтому лишь кратко пройдемся по основам, так эта часть чуть более экзотическая.
В классических реляционных базах у нас фиксированная схема — здесь же схема гибкая, каждый предикат — это фактически «колонка» и даже больше.
Представьте, что вы бы моделировали человека и хотели описать ключевые вещи, для примера возьмем конкретного человека Дугласа Адамса, за основу возьмем вот это описание.
www.wikidata.org/wiki/Q42 [18]
Если бы мы использовали реляционную базу, нам бы пришлось создать огромную таблицу или таблицы с огромным количеством колонок, большая часть из которых бы была NULL или заполнена каким-то дефолтным False значением, например, вряд ли у многих из нас есть запись в национальной корейской библиотеке — конечно, мы могли бы выносить их в отдельные таблицы, но это бы в конечном итоге была бы попытка смоделировать гибкую логическую схему с предикатами, с помощью фиксированной реляционной.
Поэтому представьте себе, что все данные хранятся в виде графа или в виде бинарных и унарных логических выражений.
Где вы вообще можете с таким столкнуться? Во-первых, работая с вики данными [19], да и с любыми графовыми базами данных или связными данными.
Далее следуют основные языки запросов, которые мне приходилось применять и с которыми приходилось работать.
Wiki:
SPARQL (рекурсивный акроним [20] от англ. [21] SPARQL Protocol and RDF Query Language) — язык запросов к данным [22], представленным по модели RDF [23], а также протокол [24] для передачи этих запросов и ответов на них. SPARQL является рекомендацией консорциума W3C [25] и одной из технологий семантической паутины [26].
А реально это язык запросов к логическим унарным и бинарным предикатам. Вы просто условно указывается, что является фиксированным в логическом выражении, а что нет (очень упрощенно).
Сама база RDF (Resource Description Framework), над которой выполняются SPARQL запросы — это тройка object, predicate, subject
— и запрос выбирает нужные тройки по указанным ограничениям в духе: найти такой X, что p_55(X, q_33) верно — где, разумеется, p_55 — это какое-то отношение с айди 55, а q_55 — это объект с айди 33 (вот и весь сказ, опять же опуская всевозможные детали).
Пример представления данных:
Картинки и пример со странами вот отсюда [27].
Пример базового запроса
Фактически мы хотим найти значение переменной ?country, такой что для предиката
member_of, верно, что member_of(?country,q458), а q458 — это ID европейского союза.
Пример реального запроса SPARQL внутри движка python:
Как правило, мне приходилось читать SPARQL, а не писать — в такой ситуации, скорее всего, это будет полезным навыком понимать язык хотя бы на базовом уровне, чтобы понять, как именно извлекаются данные.
Онлайн много материалов для изучения: например, вот этот [28] и этот [29]. Сам обычно гуглю конкретные конструкции и примеры и пока хватает.
Подробнее по теме можно прочитать в моей статье тут [30]. А здесь, мы лишь кратко разберем, почему логические языки хорошо подходят для написания запросов. По сути, RDF это просто набор вида логических утверждений вида p(X) и h(X,Y), а логический запрос имеет следующий вид:
output(X) :- country(X), member_of(X,“EU”).
Тут мы говорим, о создании нового предиката output/1 (/1 — значит унарный), при условии, что для X верно, что country(X) — т.е., Х — это страна и также member_of(X,“EU”).
То есть у нас и данные, и правила в таком случае представлены вообще одинаково, что позволяет очень легко и хорошо моделировать задачи.
Где встречались в индустрии: целый большой проект с компанией, которая пишет на таком языке запросы, а также на текущем проекте в ядре системы — казалось бы, вещь довольно экзотическая, однако иногда встречается.
Пример фрагмента кода на логическом языке, обрабатывающем wikidata:
Автор: paramonov_ruvds
Источник [39]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/356224
Ссылки в тексте:
[1] этой: https://habr.com/ru/post/275251/
[2] Хороший вводный курс от Стэнфорда: https://www.edx.org/course/databases-5-sql
[3] академических курсов: http://www.inf.unibz.it/~nutt/Teaching/FDBs1718/
[4] теоремой Кодда: https://en.wikipedia.org/wiki/Codd%27s_theorem
[5] этот: https://www.udacity.com/course/sql-for-data-analysis%E2%80%94ud198
[6] статья: https://habr.com/ru/post/152477
[7] тут: https://www.mongodb.com/nosql-explained
[8] не проблема: https://books.goalkicker.com/PythonBook/
[9] pandas: https://www.learndatasci.com/tutorials/python-pandas-tutorial-complete-introduction-for-beginners/
[10] pySpark: https://www.guru99.com/pyspark-tutorial.html
[11] Spark: https://www.udacity.com/course/learn-spark-at-udacity--ud2002
[12] DS: https://www.udacity.com/courses/school-of-data-science
[13] очень много: https://jakevdp.github.io/PythonDataScienceHandbook/
[14] эта: https://habr.com/ru/company/ruvds/blog/514990/
[15] этому: https://www.r-project.org/about.html
[16] отсюда: https://lgatto.github.io/IntroMachineLearningWithR/index.html
[17] этот: https://www.coursera.org/learn/r-programming
[18] www.wikidata.org/wiki/Q42: https://www.wikidata.org/wiki/Q42
[19] вики данными: https://www.wikidata.org/
[20] рекурсивный акроним: https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BA%D1%80%D0%BE%D0%BD%D0%B8%D0%BC
[21] англ.: https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%B3%D0%BB%D0%B8%D0%B9%D1%81%D0%BA%D0%B8%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA
[22] язык запросов к данным: https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2
[23] RDF: https://ru.wikipedia.org/wiki/Resource_Description_Framework
[24] протокол: https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB%D1%8B_%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%87%D0%B8_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
[25] консорциума W3C: https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%81%D0%BE%D1%80%D1%86%D0%B8%D1%83%D0%BC_%D0%92%D1%81%D0%B5%D0%BC%D0%B8%D1%80%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D1%83%D1%82%D0%B8%D0%BD%D1%8B
[26] семантической паутины: https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D0%BC%D0%B0%D0%BD%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BF%D0%B0%D1%83%D1%82%D0%B8%D0%BD%D0%B0
[27] отсюда: https://towardsdatascience.com/a-brief-introduction-to-wikidata-bb4e66395eb1
[28] этот: https://www.dataversity.net/introduction-to-sparql/
[29] этот: https://www.w3.org/2004/Talks/17Dec-sparql/intro/all.html
[30] тут: https://habr.com/ru/post/322900/
[31] http://peace.eas.asu.edu/aaai12tutorial/asp-tutorial-aaai.pdf: http://peace.eas.asu.edu/aaai12tutorial/asp-tutorial-aaai.pdf
[32] http://ceur-ws.org/Vol-1145/tutorial1.pdf: http://ceur-ws.org/Vol-1145/tutorial1.pdf
[33] https://www.youtube.com/watch?v=gVQ0bP8zyHw: https://www.youtube.com/watch?v=gVQ0bP8zyHw
[34] https://www.youtube.com/watch?v=kdcd7Je2glc: https://www.youtube.com/watch?v=kdcd7Je2glc
[35] https://potassco.org/book/: https://potassco.org/book/
[36] http://potassco.sourceforge.net/teaching.html: http://potassco.sourceforge.net/teaching.html
[37] https://www.cs.uni-potsdam.de/~torsten/Potassco/Tutorials/fmcad12.pdf: https://www.cs.uni-potsdam.de/~torsten/Potassco/Tutorials/fmcad12.pdf
[38] Image: http://ruvds.com/ru-rub?utm_source=habr&utm_medium=article&utm_campaign=param&utm_content=datascience3#order
[39] Источник: https://habr.com/ru/post/515820/?utm_source=habrahabr&utm_medium=rss&utm_campaign=515820
Нажмите здесь для печати.