Замена SQL-запроса на unix sort, uniq и awk - PullRequest
1 голос
/ 15 августа 2011

В настоящее время у нас есть некоторые данные о кластере HDFS, по которым мы генерируем отчеты с использованием Hive. Инфраструктура находится в процессе вывода из эксплуатации, и перед нами стоит задача создать альтернативный вариант создания отчета по данным (который мы импортировали как файлы с разделением табуляцией в нашу новую среду)

Предположим, у нас есть таблица со следующими полями.

  • Запрос
  • 1008 * IPAddress *
  • LocationCode

Наш оригинальный запрос SQL, который мы использовали для запуска в Hive, был (ну, не совсем так, но что-то похожее)

select 
COUNT(DISTINCT Query, IPAddress) as c1,
LocationCode as c2, 
Query as c3
from table
group by Query, LocationCode

Мне было интересно, может ли кто-нибудь предоставить мне наиболее эффективный скрипт, использующий стандартные инструменты unix / linux, такие как sort, uniq и awk, которые могут служить заменой для вышеуказанного запроса.

Предположим, входными данными для скрипта будет каталог текстовых файлов. каталог будет содержать около 2000 файлов. Каждый файл будет содержать произвольное количество разделенных табуляцией записей вида:

Query <TAB> LocationCode <TAB> IPAddress <NEWLINE>

Ответы [ 2 ]

1 голос
/ 27 августа 2011

Не прямой ответ на ваш первоначальный вопрос (который вы уже получили), но если у вас есть куча простых файловых данных, которые вы хотите запросить различными способами, вы можете рассмотреть возможность использования NoSQL:

http://www.strozzi.it/cgi-bin/CSA/tw7/I/en_US/nosql/Home%20Page

Этот проект NoSQL полностью отличается от (и много лет назад) того, что в последнее время стало называться «базами данных NoSQL».Вместо этого этот NoSQL связывает воедино инструменты Unix с Awk в качестве центрального элемента, чтобы упростить их использование при доступе и поддержке базы данных форматированных текстовых файлов.Позволяет легко делать много полезных вещей, например, соединения таблиц.

1 голос
/ 15 августа 2011

Как только у вас есть отсортированный файл, содержащий все уникальные

Query <TAB> LocationCode <TAB> IPAddress <NEWLINE>

Вы могли бы:

awk -F '\t' 'NR == 1 {q=$1; l=$2; count=0}
q == $1 && l == $2{count++}
q != $1 || l != $2{printf "%s\t%s\t%d\n", q, l, count; q=$1; l=$2; count=1}
END{printf "%s\t%s\t%d\n", q, l, count}' sorted_uniq_file

Чтобы получить это sorted_uniq_file, наивный путь может быть:

sort -u dir/* > sorted_uniq_file

Но это может быть очень долго и занимать память.

Более быстрым вариантом (и меньшим потреблением памяти) может быть устранение дублирования как можно скорее, сначала сортировка и последующее объединение. Для этого требуется временное пространство для отсортированного файла, давайте использовать каталог с именем sorted:

mkdir sorted;
for f in dir/*; do
   sort -u $f > sorted/$f
done
sort -mu sorted/* > sorted_uniq_file
rm -rf sorted

Если решение выше достигло некоторого предела оболочки или предела сортировки (расширение dir/*, или sorted/*, или количество параметров sort):

mkdir sorted;
ls dir | while read f; do
   sort -u dir/$f > sorted/$f
done
while [ `ls sorted | wc -l` -gt 1 ]; do
  mkdir sorted_tmp
  ls sorted | while read f1; do
    if read f2; then
      sort -mu sorted/$f1 sorted/$f2 > sorted_tmp/$f1
    else
      mv sorted/$f1 sorted_tmp
    fi
  done
  rm -rf sorted
  mv sorted_tmp sorted
done
mv sorted/* sorted_uniq_file
rm -rf sorted

Приведенное выше решение может быть оптимизировано для объединения более 2 файлов одновременно.

...