Я думаю, что основное различие, которое я могу описать, относится к форматам, ориентированным на записи и ориентированным на столбцы. Мы все привыкли к форматам, ориентированным на запись: текстовые файлы, форматы с разделителями, такие как CSV, TSV. AVRO немного круче, чем они, потому что он может со временем изменять схему, например, добавляя или удаляя столбцы из записи. Другие уловки различных форматов (особенно включая сжатие) связаны с тем, можно ли разделить формат, то есть можете ли вы прочитать блок записей из любого места в наборе данных и при этом узнать его схему? Но вот более подробная информация о столбчатых форматах, таких как Parquet.
Parquet и другие столбчатые форматы очень эффективно справляются с распространенной ситуацией с Hadoop. Обычно в таблицах (наборах данных) имеется гораздо больше столбцов, чем можно ожидать от хорошо спроектированной реляционной базы данных - сто или двести столбцов не является чем-то необычным. Это потому, что мы часто используем Hadoop как место для денормализации данных из реляционных форматов - да, вы получаете множество повторяющихся значений и множество таблиц, сведенных в одну. Но запрос становится намного проще, поскольку все соединения проработаны. Есть и другие преимущества, такие как сохранение данных о состоянии во времени. Так или иначе, это обычное дело, когда в таблице есть множество столбцов.
Скажем, есть 132 столбца, и некоторые из них представляют собой действительно длинные текстовые поля, каждый столбец идет один за другим и занимает около 10 КБ на запись.
Хотя запрос к этим таблицам прост с точки зрения SQL, часто бывает необходимо получить некоторый диапазон записей, основанный только на нескольких из этих более ста столбцов. Например, вам могут потребоваться все записи за февраль и март для клиентов с продажами> 500 долларов США.
Чтобы сделать это в формате строки, запрос должен просканировать каждую запись набора данных. Прочтите первую строку, проанализируйте запись по полям (столбцам) и получите столбцы даты и продаж, включите их в свой результат, если он удовлетворяет условию. Повторение. Если у вас 10 лет (120 месяцев) истории, вы читаете каждую запись, чтобы найти 2 из этих месяцев. Конечно, это отличная возможность использовать раздел по году и месяцу, но даже в этом случае вы читаете и анализируете 10 КБ каждой записи / строки за эти два месяца только для того, чтобы выяснить, не превышают ли продажи клиента 500 долларов.
В столбцовом формате каждый столбец (поле) записи хранится вместе с другими подобными, распределенными по множеству различных блоков на диске - столбцы за год вместе, столбцы за месяц вместе, столбцы для справочника сотрудника клиента (или другого длинный текст) и все остальные, которые делают эти записи такими огромными, все в отдельном месте на диске и, конечно же, столбцы для продаж вместе. Ну, черт возьми, дата и месяцы - это числа, как и продажи - они всего несколько байтов. Разве не было бы замечательно, если бы нам нужно было прочитать только несколько байтов для каждой записи, чтобы определить, какие записи соответствуют нашему запросу? Колонное хранилище спешит на помощь!
Даже без разделов сканирование небольших полей, необходимых для удовлетворения нашего запроса, происходит очень быстро - все они упорядочены по записи и имеют одинаковый размер, поэтому на диск требуется гораздо меньше проверок данных на наличие включенных записей. Не нужно читать это руководство сотрудника и другие длинные текстовые поля - просто игнорируйте их. Таким образом, группируя столбцы друг с другом вместо строк, вы почти всегда можете сканировать меньше данных. Выиграть!
Но подождите, станет лучше. Если вашему запросу нужно было знать только эти значения и еще несколько (скажем, 10 из 132 столбцов), и он не заботился об этом столбце справочника сотрудников, после того, как он выбрал правильные записи для возврата, теперь ему нужно было бы только пойти вернемся к 10 столбцам, необходимым для отображения результатов, игнорируя остальные 122 из 132 в нашем наборе данных. Опять же, мы пропускаем много чтения.
(Примечание: по этой причине столбчатые форматы - плохой выбор при выполнении прямых преобразований, например, если вы объединяете все две таблицы в один большой (ger) набор результатов, который вы сохраняете как новую таблицу, источники в любом случае будут полностью просканированы, поэтому не будет большого преимущества в производительности чтения, а поскольку столбцовым форматам нужно больше помнить о том, где находится материал, они используют больше памяти, чем аналогичный формат строки).
Еще одно преимущество колоночного типа: данные разбросаны. Чтобы получить одну запись, у вас может быть 132 воркера, каждый из которых читает (и записывает) данные из / в 132 разных места на 132 блоках данных. Ура за распараллеливание!
А теперь решающий аргумент: алгоритмы сжатия работают намного лучше, когда они могут находить повторяющиеся шаблоны. Вы могли сжать AABBBBBBCCCCCCCCCCCCCCCC
столько же, 2A6B16C
но ABCABCBCBCBCCCCCCCCCCCCCC
не получилось бы таким маленьким (ну, вообще-то, в этом случае было бы, но поверьте мне :-)). Так что еще раз меньше читать. И писать тоже.
Таким образом, мы читаем намного меньше данных, чтобы отвечать на общие запросы, потенциально быстрее читать и писать параллельно, а сжатие работает намного лучше.
Columnar отлично подходит, когда ваша входная сторона большая, а ваш вывод представляет собой отфильтрованное подмножество: от большого к маленькому - отлично. Не так выгодно, когда входы и выходы примерно одинаковы.
Но в нашем случае Impala взяла наши старые запросы Hive, которые выполнялись за 5, 10, 20 или 30 минут, и завершила большинство за несколько секунд или минут.
Надеюсь, это поможет ответить хотя бы на часть вашего вопроса!