Graffiti
| Graffiti | |
| Стабильная версия: | |
|---|---|
| Дата релиза: |
25 декабря 2011 |
| Тип программы: | |
| Лицензия: | |
| Операционная система: | |
| Разработчик | |
| Веб-сайт: | |
Graffiti — хранилище RDF-данных на основе динамического преобразования RDF-запросов в SQL. Graffiti позволяет отобразить любую реляционную схему данных на модель RDF и наоборот, хранить любые RDF-данные в реляционной СУБД.
С 2003 года данная система хранения RDF-данных использовалась в качестве основного средства доступа к данным в системе открытой публикации Samizdat, с 2010 года она выделена в независимый модуль, который может быть использован в других приложениях, написанных на языке Ruby.
Содержание |
Реализация и развёртывание
RDF-хранилище Graffiti реализовано на языке Ruby в виде библиотеки, предоставляющей прикладной программный интерфейс для выполнения RDF-запросов на языке Squish. Пример кода:
require 'sequel'
require 'yaml'
require 'graffiti'
db = Sequel.connect(:adapter => 'pg', :database => dbname)
config = File.open('rdf.yaml') {|f| YAML.load(f.read) }
store = Graffiti::Store.new(db, config)
data = store.fetch(%{
SELECT ?date, ?title
WHERE (dc::date ?r ?date FILTER ?date >= :start)
(dc::title ?r ?title)
ORDER BY ?date DESC}, 10, 0, :start => Time.now - 24*3600)
puts data.first[:title]
Для подключения к реляционным СУБД используется модуль Sequel. Поддерживаются СУБД PostgreSQL (полностью), MySQL, SQLite (частично). Для кэширования преобразованных запросов используется библиотека SynCache, которая может размещать кэш как в памяти прикладного процесса, так и на отдельном сервере (в последнем случае используется протокол удалённого вызова процедур DRuby).
Адаптация реляционных данных
Любая таблица, соответствующая первой нормальной форме, может быть отображена для доступа при помощи RDF-запросов на языке Squish. Адаптация под Graffiti включает добавление в базу данных атрибутов, внешних ключей, таблиц и хранимых процедур, необходимых для преобразования запросов RDF и поддержки дополнительных возможностей, таких как реификация утверждений и логический вывод на правилах для терминов rdfs:subClassOf, rdfs:subPropertyOf и owl:TransitiveProperty.
Следующие изменения схемы базы данных обязательны во всех случаях:
- создать таблицу ресурсов, отображённую на суперкласс
rdfs:Resource, с автоматически генерируемым первичным ключом; - заменить первичные ключи таблиц, отображённых на подклассы класса
rdfs:Resource, на внешние ключи, ссылающиеся на таблицу ресурсов (может потребоваться также обновить существующие внешние ключи, чтобы отразить это изменение); - зарегистрировать хранимые процедуры логического вывода на правилах для
rdfs:subClassOfдля обновления таблицы ресурсов и поддержки целостности внешних ключей при выполнении операций над таблицами подклассов.
Следующие изменения могут потребоваться для поддержки дополнительных возможностей алгоритма преобразования запросов:
- зарегистрировать хранимые процедуры для прочих случаев логического вывода на правилах для
rdfs:subClassOf; - создать таблицу триплетов (необходимо для представления RDF-данных, не отображённых на реляционную схему, и реификации утверждений RDF);
- добавить атрибуты различения подотношений, ссылающиеся на записи в таблице ресурсов, хранящие идентификаторы
URIrefсоответствующих отношений, для каждого атрибута, отображённого на подотношение; - создать таблицы транзитивных замыканий и зарегистрировать хранимые процедуры логического вывода на правилах для
owl:TransitiveProperty.
Отображение предикатов RDF на таблицы и поля реляционной схемы данных задаётся в динамически подгружаемом файле в формате YAML (rdf.yaml в примере выше). Пример конфигурации и хранимых процедур для системы открытой публикации Samizdat приведен в исходниках Graffiti:
Язык запросов
Graffiti реализует расширенную версию языка запросов Squish. Поддерживаются следующие дополнительные конструкции:
- внешнее определение пространств имён;
- условия фильтрации результатов;
- задание сортировки и агрегации результатов;
- параметризованные запросы;
- необязательные и отрицательные графовые шаблоны.
Запрос на расширенной версии языка Squish может включать следующие части, выделяемые соответствующими ключевыми словами:
-
SELECT: список выражений, входящих в результаты запроса; -
WHERE: основной графовый шаблон; -
EXCEPT: отрицательный графовый шаблон; -
OPTIONAL: необязательный графовый шаблон; -
LITERAL: глобальное условие фильтрации результатов; -
GROUP BY: правила агрегации результатов; -
ORDER BY: правила сортировки результатов; -
USING: определение пространств имён.
Возможности языка запросов, реализованные в Graffiti, в сравнении с другими системами хранения RDF в реляционных базах данных — Federate, D2RQ и Virtuoso:
| Graffiti | Federate | D2RQ | Virtuoso | |
|---|---|---|---|---|
| Синтаксис SPARQL | нет | нет | да | да |
| Простой графовый шаблон | да | да | да | да |
| Условия фильтрации | да | нет | да | да |
| Необязательный графовый шаблон | да | да | частично | да |
| Вложенные группы графовых шаблонов | частично | нет | нет | да |
| Неопределённые предикаты | нет | нет | нет | да |
| Реификация утверждений | да | нет | нет | нет |
| Логический вывод для RDFS | частично | нет | нет | частично |
| Логический вывод для OWL | частично | нет | нет | частично |
| Агрегация результатов | да | нет | нет | да |
| Язык обновления данных | да | нет | нет | да |
Производительность
Тестирование на реальных наборах данных сайтов, использующих систему открытой публикации Samizdat, показывают, что Graffiti при работе с реляционной базой данных под управлением PostgreSQL показывает среднюю производительность порядка сотен запросов в секунду. Например, на наборе данных размером порядка 100 тыс. триплетов перегенерация главной страницы сайта требует выполнения различных 997 запросов на языке Squish и завершается за 7,7 с. Снижение производительности с ростом размера набора данных остаётся незначительным до тех пор, пока база данных может быть целиком размещена в доступной оперативной памяти: в той же тестовой среде перегенерация главной страницы для набора данных из 1 тыс. ресурсов RDF (порядка 10 тыс. триплетов) завершается за 6,4 с, а для набора данных из 230 тыс. ресурсов (порядка 1 млн. триплетов) — за 13,6 с.
Для более достоверного сравнения с другими RDF-хранилищами было проведено тестирование по методике Berlin SPARQL Benchmark (BSBM). Следует отметить, что полученные результаты нельзя считать официальными показателями производительности, так как полностью выполнить все требования спецификации BSBM не удалось. Стандартный тестовый драйвер, написанный на Java и использующий язык запросов SPARQL, не совместим с Graffiti, поэтому вместо него был разработан драйвер, дублирующий функциональность стандарного драйвера, со следующими изменениями: использование запросов на языке Squish вместо SPARQL, использование параметризованных запросов, использование Ruby API вместо протокола SPARQL, отсутствие квалификационного режима. Вместо автоматической квалификации на уровне тестового драйвера, результаты выполнения тестовых запросов проверялись вручную.
Использовались следующие версии программного обеспечения: ОС Debian squeeze/sid, ядро Linux 2.6.30, СУБД PostgreSQL 8.4.0, интерпретаторы Java 1.6.0.15 и Ruby 1.9.0, библиотеки JDom 1.1, ruby-pg 0.8.0, ruby-dbi 0.4.2, ruby-dbd-pg 0.3.8, SynCache 1.0 и Graffiti 1.0. В тестовом стенде было использовано следующее аппаратное обеспечение: процессор Intel Core 2 Duo E6850 2,66 ГГц с 4 Мб кэша L2; 2 Гб ОЗУ PC3-10600; жёсткий диск SATA 500 Гб 10000 rpm. Данный стенд соответствует стенду, использованному в официальных тестах BSBM, по всем параметрам, кроме объёма и модели ОЗУ (2 Гб ОЗУ вместо 8 Гб, DDR3 вместо DDR2), и количества ядер процессора (2 вместо 4, что не должно было повлиять на однопоточные тесты).
Тестирование проводилось на 5 наборах данных: помимо стандартных 1, 25 и 100 млн. триплетов, были протестированы наборы в 250 тыс. и 5 млн. триплетов, что позволило более точно оценить изменение производительности Graffiti с ростом объёма обрабатываемых данных как в пределах доступного объёма ОЗУ, так и при выходе за эти пределы:
| Набор данных | 250K | 1M | 5M | 25M | 100M |
|---|---|---|---|---|---|
| Количество товаров | 666 | 2810 | 14208 | 70812 | 284826 |
| Объём данных на диске | 65 Мб | 260 Мб | 1,1 Гб | 5,2 Гб | 21 Гб |
Набор скриптов, использованных в тестах:
Совокупная производительность QMpH (серий запросов в час):
| Набор данных | 250K | 1M | 5M | 25M | 100M |
|---|---|---|---|---|---|
| Полная серия запросов | 25896 | 25287 | 23493 | 18735 | 2246 |
| Сокращённая серия запросов | 28184 | 28986 | 27534 | 24884 | 2356 |
Производительность Graffiti на полной серии запросов на фоне официальных результатов систем Jena SDB, Sesame NS, D2RQ и Virtuoso RV:
При сравнении с официальными результатами BSBM следует учитывать следующие особенности Graffiti и использованной методики тестирования:
- Использование Ruby API вместо сетевого протокола
- Более эффективное кэширование преобразованных запросов за счёт использования параметризованных запросов
- Разделение преобразования и выполнения запроса между двумя процессами (интерпретатор Ruby и сервер PostgreSQL), позволяющее задействовать два ядра процессора даже в однопоточных тестах
- Использование полнотекстового индекса PostgreSQL для поиска по подстроке на порядок повысило скорость обработки запроса 6 («Find products having a label that contains a specific string»)
- Тестовый стенд использовал ОЗУ меньшего объёма, но с более высокой пропускной способностью (DDR3-1333 вместо DDR2-667), что частично компенсируется меньшим объёмом кэша L2 (4 Мб вместо 12 Мб)

