Ермаков Е.Ю.
МГТУ им Н.Э.Баумана, аспирант [email protected]
Анализ и сравнение процессов обработки запроса к таблице в параллельных колоночных и строчных
хранилищах данных
Аннотация
В статье проанализированы существующие методы выполнения запросов в параллельной колоночной СУБД. Приведено сравнение процессов обработки запросов в строчной и колоночной СУБД. Приведено сравнение времени обработки запроса с планом па(ор(я)) в параллельной построчной и колоночной СУБД.
Ключевые слова. Параллельные колоночные базы данных, преобразование Лапласа-Стилтьеса, сравнение строчных и колоночных систем
Введение
К настоящему времени во многих организациях накоплены колоссальные объемы данных, на основе которых можно решать самые разнообразные аналитические и управленческие задачи в любой сфере деятельности. Проблемы хранения и обработки аналитической информации становятся все более актуальными и привлекают внимание специалистов и фирм, работающих в области информационных технологий. Именно на решение этих задач направлены технологии, объединяющиеся под общим названием хранилища данных и бизнес-анализа. По оценке Gartner, хранилища в ближайшей перспективе останутся одними из ключевых компонентов автоматизированных информационных систем предприятий [1].
Несмотря на то, что классические реляционные хранилища обеспечивают наилучшее сочетание простоты, устойчивости, гибкости, производительности, масштабируемости и совместимости, их показатели по каждому из этих пунктов не обязательно выше, чем у аналогичных систем, ориентированных на какую-то одну особенность. Согласно Майклу Стоунбрейкеру, пионеру исследований в области больших баз данных [2], такая идея «безразмерности», когда традиционная архитектура СУБД, изначально разработанная и оптимизированная для обработки бизнес-данных, используется для поддержки приложений, требующих обработки больших объемов данных, больше не применима к рынку баз данных. Мир коммерческих СУБД будет дробиться на набор независимых, специализированных средств управления базами данных [3].
Одним из основных и самых перспективных архитектурных решений
для специализированных СУБД в области хранилищ данных является колоночное хранение данных: большой потенциал колоночных систем подтверждают аналитические исследования и прогнозы аналитиков [1,3-5]. Например, в работе [5] показано 200-кратное сокращение объема ввода-вывода по сравнению с аналогичной реляционной СУБД (РСУБД). Это достигается за счёт того, что из базы данных читаются только те атрибуты, которые участвуют в запросе, а также применяются эффективные методы сжатия столбцов.
Таким образом, перед проектировщиком системы обработки данных возникает непростая задача выбора между традиционными (строчными -Oracle, MS SQL Server и др.) и специализированными СУБД (колоночными -Vertica, ParAccel и др.). Для принятия обоснованного технического решения по выбору типа СУБД необходимо использовать средства моделирования. Для традиционных РСУБД такие методы уже существуют [6]. Для параллельных СУБД подобные исследования ведутся [7-10].
В статье выполнено сравнение процессов обработки запросов в параллельной строчной и колоночной системе баз данных, а также времени выполнения запроса к одной таблице на основе математические методов, предложенных авторами в статьях [11,12] и учитывающих особенности выполнения запросов к колоночным и строчным СУБД. Организация работы строчного и колоночного СУБД Под строчным хранением данных обычно понимается физическое хранение кортежа любого отношения в виде одной записи, в котором значения атрибута идут последовательно одно за другим, а за последним атрибутом кортежа в общем случае следует новый кортеж отношения. Таким образом, на физическом носителе отношение R представлено в следующем виде:
[¿ii- а31.....а „ н ] j. Idj.,, d „.....d 21dM, d ,g......ri s] a... [n- ж' агт> — ' HnntJ m ГДе CLj'
значение атрибута а,- в j-м кортеже отношения R,
ldij'd2j.....<hi}]j - j-й кортеж отношения R,
n - количество атрибутов отношения R, m= " ,г - количество кортежей отношения R.
В колоночных хранилищах значения одного атрибута хранятся последовательно друг за другом [1], т.е. на физическом носителе отношение R примет следующий вид.
—• ^lmiii^fl' •••■> ^iin^I ■■■ i^fil' BnJ'-" ' Oilman.,
где dy -значение атрибута Q; в j-м кортеже отношения R,
{¿л.а^Лц.....- i-й столбец (атрибут) отношения R
Каждая колонка, хранимая на диске, разделена на блоки определенного размера. Блок состоит из заголовка, размер которого пренебрежительно мал по сравнению с размером блока и непосредственно данных. При одном запросе к диску происходит чтение нескольких блоков, количество которых определяется параметром. Каждой записи в столбце
сопоставляется ее позиция (номер строки). В большинстве современных колоночных БД [14] значения столбца упорядочиваются по позициям.
На логическом уровне колоночные и строчные СУБД идентичны, т.е. способны обрабатывать одни и те же SQL-запросы. Но отличия в физической организации хранения данных существенно влияют на реализацию процессов, протекающих при формировании плана выполнения запроса и его реализации.
В строчных СУБД план запроса представляет собой дерево, у каждого узла которого имеется один родитель и один (или два в случае пересечения) дочерних узла [15]. Реализация исполнителя планов базируется на следующих трех базовых парадигмах [15]: синхронный конвейер, итераторная модель, скобочный шаблон.
Синхронный конвейер. Суть данного метода состоит в том, что, как только операция получает очередной кортеж своего результирующего отношения, она передаёт его по конвейеру выше стоящей операции для обработки. Например, узел, читающий записи из исходной таблицы, передаёт их узлу, выполняющему соединение записей разных таблиц.
root.reset;
while(!EOF(t=root.next))print(t) ,
reset>^\ "next K'
Рис 1. Выполнение плана запроса на базе итераторной модели
Итераторная модель._Эта модель является общепринятым методом, используемым в СУБД для эффективной реализации синхронного конвейера. В соответствие с итераторной моделью с каждым узлом дерева плана запроса связывается специальная структура управления, называемая итератором. Интерфейс итератора представлен двумя стандартными операциями с предопределенной семантикой:
reset - установка итератора в состояние "перед первым кортежем", next - выдать очередной кортеж результирующего отношения. Алгоритм выполнения плана запроса на базе итераторной модели изображён на рис.1. На первом шаге выполняется метод reset применительно к корневому узлу. Затем в цикле выполняется метод next
для корневого узла. Он каждый раз возвращает указатель на очередной кортеж результирующего отношения. Цикл завершается, когда метод next выдает указатель на специальный кортеж, обозначающий конец файла -EOF (End Of File). Методы reset и next родителя прямо или косвенно могут вызывать соответствующие методы дочерних узлов. Эти вызовы изображены на рисунке пунктирными стрелками. Реализация итератора базируется на скобочном шаблоне, который рассмотрен ниже. Скобочный шаблон. Основными атрибутами являются
• выходной буфер, в который помещается кортеж результата;
• КОП - код реляционной операции, реализуемой данным узлом;
• указатель на скобочный шаблон левого дочернего узла;
• указатель на скобочный шаблон правого дочернего узла ("пусто" для унарных операций).
Сам по себе скобочный шаблон не содержит конкретной реализации реляционной операции. Однако, после оптимизации запроса СУБД "вставляет" в каждый скобочный шаблон ту или иную реализацию соответствующей реляционной операции. Например, для операции соединения СУБД может выбрать один из следующих кодов: "соединение вложенными циклами", "соединение сортировкой и слиянием", "соединение хешированием". При выполнении этой операции узел обращается к скобочным шаблонам дочерних узлов.
Рассмотрим, какие изменения вносят колоночные базы данных в каждый из рассмотренных принципов.
t
í
ОП1
{POS}
t
{POS}
í
ОП4
{POS} {P(
t t
^ ОП5 ОП6
Рис. 2. Пример синхронного конвейера колоночного хранилища Синхронный конвейер. В колоночных СУБД при реализации конвейера учитываются следующие особенности:
• в связи с фундаментальными отличиями в организации хранения информации на физическом носителе операции выполняются не над кортежами отношения, а над блоками атрибутов отношения;
• существует возможность проводить операции не над данными (блоками), а над позициями значений в этих блоках;
• между узлами конвейера могут передаваться как позиции, так и указатели на блоки данных.
Пример конвейера колоночного хранилища для простого запроса по двум атрибутам таблицы, использующего вышеперечисленные возможности, представлен на рис. 2. Результатами операций 5 и 6 являются позиции значений в атрибутах. Списки полученных позиций передаются и обрабатываются (соединяются, пересекаются и т.п.) в операторе 4, результат действия которого попадает в операторы 2 и 3, считывающие указанные в полученном наборе позиций значения.
Итераторная модель. Для колоночных хранилищ характерны следующие изменения:
• возможно наличие нескольких родительских узлов, т.е. результаты операции передаются не единственному следующему оператору;
• используются как итераторы по кортежам, так и по блокам;
• вводится операция материализации кортежа: получение исходного или необходимого на данном этапе кортежа на основе передаваемых блоков значений атрибута.
Скобочный шаблон. Для колоночных систем в скобочный шаблон не вносится значительных изменений. Меняется формат выходных данных: это могут быть как кортежи, так и позиции элементов и указатели на блоки данных.
Основной формой параллельной обработки запросов в строчных и колоночных СУБД является фрагментный параллелизм. Подробно данный процесс рассмотрен в работах [7-10,15]. В соответствие с этой схемой запрос на языке SQL преобразуется в некоторый последовательный план. Данный последовательный план преобразуется в параллельный план, представляющий собой совокупность n идентичных параллельных агентов, которые реализуют те же операции, что и последовательный план. На завершающем этапе агенты рассылаются на соответствующие процессорные узлы, где интерпретируются исполнителем запросов. Результаты выполнения агентов объединяются корневым оператором exchange на нулевом процессорном модуле.
Наиболее распространенной системой классификации параллельных систем баз данных является система, предложенная Майклом Стоунбрейкером (Michael Stonebraker) [15]:
4.SE (Shared-Everything) - разделяемые память и диски. 5.SD (Shared-Disks) - разделяемые диски.
6.SN (Shared-Nothing) - без совместного использования ресурсов. Особенности обработки запросов в колоночных СУБД
Одним из процессов при формировании ответа на запрос в колоночных базах данных является материализация кортежей - процесс воссоздания кортежа на основе столбцов-атрибутов. В зависимости от момента применения данной операции в плане запроса в [16] предлагается
следующие варианты материализации.
Ранняя материализация. Данный вариант аналогичен «естественной» материализации, применяемой в строчных СУБД: каждый раз, когда осуществляется доступ к атрибуту, он добавляется к кортежу.
Поздняя материализация. Специфика колоночных СУБД позволяет отложить процесс материализации до определенного момента, используя в процессе выполнения запроса позиции значений в колонках вместо самих значений атрибутов. К преимуществам данного метода можно отнести более высокую скорость работы с позициями значений по сравнению со всем кортежем. Слабым местом такого подхода является необходимость двойного чтения данных из столбца - в первом случае для получения позиций, во втором, уже после анализа и преобразования номеров, для получения значений.
Таким образом, операцию материализации можно рассматривать в качестве момента, после которого исполнитель запросов начинает применять классические покортежные операции.
В работе [16] предлагается следующие столбцов: параллельный и последовательный. колонки считываются независимо друг от материализации после считывания полученные битовые маски пересекаются, и на основе результирующей битовой маски происходит чтение остальных атрибутов, участвующих в операции проекции. При последовательной обработке, в отличие от параллельной, атрибуты, участвующие в запросе, упорядочиваются по убыванию селективности и считываются по очереди. В каждую следующую операцию чтения атрибута передается битовая маска предыдущего чтения (рис.3).
варианты обработки В первом случае все друга. При поздней
□ 1
Рис.3. Иллюстрация особенности последовательной обработки Подобная организация процесса чтения атрибутов позволяет уменьшить количество операций чтения блоков данных с диска. На рис. 3 показаны колонки атрибутов. Перечёркнуты те блоки, которые не надо считывать, т.к. соответствующие записи не удовлетворяют условию поиска по предыдущим атрибутам.
В современных СУБД широко используется сжатие данных. Это позволяет повысить производительность за счет уменьшения числа дисковых операций ввода-вывода и объёма передаваемых по сети данных. Колоночное хранение отношений позволяет улучшить этот показатель по
0
0
0
0
0
0
0
0
0
0
0
сравнению со строчными СУБД. Это достигается за счет использования коэффициентов повторяемости значений атрибутов и возможности оперировать сжатыми данными (т.е. отсутствия затрат на декомпрессию). В работе [17] предлагается полученный эмпирическим путем алгоритм выбора типа компрессии данных в столбцах.
Преобразования Лапласа-Стилтьеса времени выполнения запроса к таблице в строчной и колоночной системе баз данных
В [8] приведено преобразование Лапласа-Стилтьеса (ПЛС) времени выполнения запроса к строчной базе данных с планом Ua(qf(R)), п -операция проекции, о - операция селекции. В [12] приведены формулы для фв (s), фм (s) ,фн (s) (т.е. для ПЛС времени обработки кортежей в ресурсах) для различных режимов функционирования системы баз данных и различных архитектурных решений. При выводе учитывались следующие особенности выполнения запроса в колоночной СУБД [11]:
• каждая колонка хранится на диске в своих блоках, где отдельная колонка представляет собой таблицу с кортежем (значение атрибута, позиция)
• последовательная и параллельная обработка запросов с поздней материализацией кортежей,
• наличие компрессии данных (метод RLE),
• получение времени работы обслуживающих устройств на основе измеримых с помощью синтетических тестов показателей.
При этом рассматривались два режима работы [12]:
1. Пакетный режим (offline, система рассматривается как замкнутая). При данном режиме работы в колоночной системе баз данных обрабатываются пакеты запросов, В каждом пакете SQL-запросы выполняются последовательно (предполагается, что они связаны по данным: выходные данные одного запроса являются входными данными другого). Но запросы разных пакетов (по одному из каждого пакета) могут обрабатываться параллельно. Предполагается, что «узкое место» в данном режиме-дисковая система.
2. Режим «запрос-ответ» (online, система рассматривается как разомкнутая).При данном режиме работы предполагается, что i-ая рабочая станция обращается к j-ому запросу c некоторой интенсивностью. При условии, что эти входные потоки заявок являются пуассоновскими, время обслуживания в ресурсах распределено по экспоненциальному закону, а переход от ресурса к ресурсу выполняется по вероятности, модель обработки запросов можно представить в виде сети массового обслуживания. В этой сети обработку в узлах ресурсов можно представить в виде совокупности независимых СМО М/М/1 (это доказывается в теории массового обслуживания в виде теоремы разложения Джексона).
Сравнение среднего времени обработки запроса к одной таблице в строчной и колоночной базе данных
Оценку среднего времени выполнения запроса можно получить, дифференцируя выражения ПЛС времени обработки запроса в нуле (в работе [12] были использованы численные методы).
Ниже приведены результаты расчёта отношения среднего времени обработки простого запроса Ua(qf(R)) в строчной СУБД к среднему времени выполнения этого запроса в колоночной СУБД в зависимости от отношения количества атрибутов, участвующих в запросе, к общему количеству атрибутов в таблице.
Для упрощения расчетов будем считать, что Ka=Kf=K т.е. количество атрибутов, участвующих в операции фильтрации, равно количеству атрибутов, использующихся в операции проекции. Также примем, что таблица состоит из H=100 одинаковых по размеру и типу атрибутов. Расчёты были выполнены при следующих значениях характеристик ресурсов.
1. Процессор - Intel Xeon 5160. Для выбранного процессора измеренное значение числа процессорных циклов, выполняемых секунду -Цр=1.5-109(1/С).
2. Внешняя память - N=50 дисков 3.5'' Seagate Cheetah 15K.6 ST3146356FC; размер блока чередования (stripe size) - Qb4=64 Кб; среднее время поиска и чтения блока чередования с диска - tB4 = подвода + tвращения/2 + Qвч/vчтения = 4 + 4/2 + 64/200 = 6.3 мс. Поэтому интенсивность чтения блоков с диска равна ^db= 1000/6.3= 160 (1/с).
3. Оперативная память - DDR3-1600 PC3- 12800. Интенсивность чтения одного байта информации из ОП равна Цм= 9586-1024-1024 (1/с).
4. Остальные параметры для расчетов приведены ниже.
V=106 ri=20 L=100 P2=0.007
P1=0.01 u=50 H=100 Pd=0.9
L - среднее число записей таблицы R в блоке чередования для строчной СУБД, kc - среднее число позиций, покрываемых одним кортежем столбца колоночной базы данных, kc=1 - нет сжатия.
Графики отношения времени выполнения запроса в строчной СУБД к времени выполнения запроса в колоночной СУБД (Y) в зависимости от отношения количества атрибутов, участвующих в запросе, к общему количеству атрибутов в таблице (X= 100*2*K/H) для различного среднего числа позиций, покрываемых одним кортежем (kc учитывает сжатие), представлены на рис.4. Графики построены для числа процессоров n=2. В табл. 1 приведены значения Y для некоторых X.
Табл.1. Результаты вычислений.
kc=1 kc=5 kc=10
X=2% (Ka=Kf=1) 31 70 99
X=65% 1 2,5 3,8
X=100% 0,66 1,65 2,5
Из графиков видно, что при использовании менее 20% атрибутов
время выполнения запроса в колоночной СУБД меньше в разы по сравнению со строчной СУБД, при большем количестве атрибутов время выполнения запроса растет практически пропорционально числу используемых в запросе атрибутов. Для кс=1 (нет сжатия данных) среднее время выполнения запроса в строчной и колоночной СУБД становится равным ^=1) при использовании 65% атрибутов (табл. 1). Увеличение времени выполнения запроса в колоночной СУБД при большем количестве используемых атрибутов можно объяснить ростом числа читаемых с диска столбцов таблицы (для строчных СУБД время не изменяется, т.к. с диска записи читаются целиком). При Х=100% и кс=1 среднее время выполнения запроса в строчной СУБД в 1.5 (1/0.66) раза меньше, чем в колоночной СУБД. При достаточно хорошем сжатии столбцов таблицы картина меняется: колоночная СУБД лучше строчной даже при использовании в запросе 100% атрибутов (см. табл. 1).
На рис. 5 представлены графики зависимости среднего времени выполнения запроса в колоночной СУБД от числа процессоров для различного соотношения используемых в запросе атрибутов (10%, 50%, 100%), а также время выполнения запроса в строчной СУБД. Из графиков видно, что для строчной СУБД пятнадцатисекундная отметка среднего времени обработки запроса достигается при числе процессоров п=10. Для колоночной СУБД эта отметка достигается при соотношении используемых в запросе атрибутов 10% (10 атрибутов из 100) уже при п=2 (и это при отсутствии сжатия столбцов, кс=1).
Рис. 4. Отношение времени выполнения запроса в строчной СУБД к времени выполнения запроса в колоночной СУБД (У) в зависимости от отношения количества атрибутов,участвующих в запросе, к общему количеству атрибутов в таблице (X, %) при разных 'кс.
Заключение
1. Проанализированы процессы выполнения запросов в строчной и колоночной системе баз данных. Рассмотрены изменения, вносимые в синхронный конвейер, итераторную модель и скобочный шаблон, а также операции материализации и компрессии данных для колоночных СУБД.
2. Выполнено сравнение среднего времени выполнения запроса с
планом TCA(aF(R)) в строчной и колоночной СУБД. Приведён пример расчёта отношения среднего времени выполнения запроса в строчной СУБД к среднему времени выполнения запроса в колоночной СУБД в зависимости от отношения количества атрибутов, участвующих в запросе, к общему количеству атрибутов в таблице. На его основании можно сделать вывод о том, что при хорошем сжатии столбцов (см. kc) время выполнения запроса в колоночной СУБД меньше, чем в строчной СУБД даже при использовании в
запросе 100% атрибутов (см. табл. 2).
100 90 80 70 60 50 40 30 20 10 О
Рис. 5. Среднее время выполнения запроса в колоночной СУБД (с.) в зависимости от числа процессоров для различного отношения используемых в запросе атрибутов и время выполнения запроса в строчной СУБД (везде
k=1).
3. Для колоночной СУБД десятисекундная отметка среднего времени выполнения запроса при отношении используемых в запросе атрибутов 10% достигается при меньшем числе процессоров (n=2), чем для строчных СУБД (n=15). Это свидетельствует об экономии вычислительных ресурсов при использовании колоночных СУБД.
4. Предполагается продолжить исследования и получить оценки времени выполнения запросов с более сложными планами реализации (например, для плана выполнения запроса к хранилищу данных типа «звезда»).
Литература
1. Андрей Арсентьев. Хранилища данных становятся инфраструктурным компонентом №1. CNews аналитика. 2010. [Электронный ресурс]. [http://retail.cnews.ru/reviews/free/BI2010/articles/articles6.shtml]. Проверено 27.06.2011.
2. Michael Stonebraker Biography, 2008 г. [Электронный ресурс] [http://www.csail.mit.edu/user/1547]. Проверено 28.06.2012.
3. Michael Stonebraker, Ugur fetintemel. «One Size Fits All»: An Idea Whose Time Has Come and Gone. / Перевод Сергея Кузнецова, 2007 г.: [Электронный ресурс]. [http://citforum.ru/database/articles/one_size_fits_all/]. Проверено 27.06.2011.
4. Michael Stonebraker, Chuck Bear, Ugur fetintemel, Mitch Cherniack, Tingjian Ge, Nabil Hachem, Stavros Harizopoulos, John Lifter, Jennie Rogers, and Stan Zdonik. One Size Fits All? -Part 2: Benchmarking Results. 3rd Biennial Conference on Innovative Data Systems Research (CIDR), January 7-10, 2007, Asilomar, California, USA. / Перевод Сергея Кузнецова, 2007 г.: [Электронный ресурс].
5. [http://citforum.ru/database/articles/one_size_fits_all_2/]. Проверено 27.06.2011.
6. Michael Stonebraker. My Top 10 Assertions About Data Warehouses. / Перевод Сергея Кузнецова, 2010 г.: [Электронный ресурс]. [http://citforum.ru/gazeta/166/]. Проверено 27.06.2011.
7. Григорьев Ю.А., Плутенко А.Д. Теоретические основы анализа процессов доступа к распределенным базам данных. Новосибирск: Наука, 2002. - 222 с.
8. Ю.А. Григорьев, В.Л. Плужников. Оценка времени выполнения запросов и выбор архитектуры параллельной системы баз данных. МГТУ,2009.
9. Григорьев Ю.А., Плужников В.Л. Модель обработки запросов в параллельной системе баз данных // Вестник МГТУ им. Н.Э. Баумана. - 2010. - № 4. - С. 78-90.
10. Григорьев Ю.А., Плужников В.Л. Оценка времени соединения таблиц в параллельной системе баз данных// Информатика и системы управления. - 2011. - № 1. -С. 3-16.
11. Григорьев Ю.А., Плужников В.Л. Анализ времени обработки запросов к хранилищу данных в параллельной системе баз данных // Информатика и системы управления. - 2011. - № 2. - С. 94-106.
12. Григорьев Ю.А., Ермаков Е.Ю. Модель обработки запросов в параллельной колоночной системе баз данных // Информатика и системы управления. - 2012. - № 1. - С. 3-15.
13. Григорьев Ю.А., Ермаков Е.Ю. Модель обработки запроса к одной таблице в параллельной колоночной системе баз данных и анализ ее адекватности // Информатика и системы управления. - 2012. - № 2. - С. 170-179.
14. Michael Stonebraker, Daniel J. Abadi, Adam Batkin, Xuedong Chen, Mitch Cherniack, Miguel Ferreira, Edmond Lau, Amerson Lin, Samuel R. Madden, Elizabeth J. O'Neil, Patrick E. O'Neil, Alexander Rasin, Nga Tran, and Stan B. Zdonik: C-Store: A Column-Oriented DBMS [Электронный ресурс]. [http://www.cs.yale.edu/homes/dna/pubs/displaypubs.cgi/]. Проверено 22.10.2011.
15. Daniel J. Abadi Query Execution in Column-Oriented Database Systems. [Электронный ресурс]. [http://www.cs.yale.edu/homes/dna/papers/abadiphd.pdf]. Проверено 25.12.2011.
16. Соколинский Л. Б., Цымблер М. Л. Лекции по курсу "Параллельные системы баз данных": [Электронный ресурс]. [http://pdbs.susu.ru/CourseManual.html]. Проверено 22.10.2011.
17. Daniel J. Abadi, Daniel S. Myers, David J. DeWitt, and Samuel R. Madden. Materialization Strategies in a Column-Oriented DBMS In Proceedings of ICDE, 2007. [Электронный ресурс]. [http://db.lcs.mit.edu/projects/cstore/abadiicde2007.pdf]. Проверено 25.12.2011.
18. Daniel J. Abadi, Samuel R. Madden and Miguel C. Ferreira. Integrating Compression and Execution in Column-Oriented Database Systems In Proceedings of ICDE, 2006. [Электронный ресурс]. [http://db.lcs.mit.edu/projects/cstore/abadisigmod06.pdf]. Проверено 25.12.2011.