Этот пост представляет собой резюме второго дня Hbase из книги « Семь баз данных за семь недель» .
Большинство команд и скриптов можно найти на GitHub: https://github.com/eyalgo/seven-dbs-in-seven-weeks/tree/master/hbase/day_2
Потоковый скрипт
Первым делом во второй день была загрузка большого количества данных (больших данных) и их передача в Hbase. Есть сценарий JRuby, который мне пришлось изменить, чтобы он работал: https://github.com/eyalgo/seven-dbs-in-seven-weeks/blob/master/hbase/day_2/import_from_wikipedia.rb
После ее изменения, как было предложено в книге, мне пришлось добавить некоторое сжатие в семейство столбцов. После этого я мог запустить скрипт:
|
1
2
3
|
curl http://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2 | bzcat | /opt/hbase/hbase-0.94.18/bin/hbase shell /home/eyalgo/seven-dbs-in-seven-weeks/hbase/day_2/import_from_wikipedia.rbcurl http://dumps.wikimedia.org/enwiktionary/latest/enwiktionary-latest-pages-articles.xml.bz2 | bzcat | /opt/hbase/hbase-0.94.18/bin/hbase shell import_from_wikipedia.rb |
Это вывод при запуске скрипта
|
1
2
3
4
|
1 10.0G 1 128M 0 0 456k 0 6:23:37 0:04:48 6:18:49 817k19000 records inserted (Serotonin) 1 10.0G 1 131M 0 0 461k 0 6:19:03 0:04:51 6:14:12 921k19500 records inserted (Serotonin specific reuptake inhibitors) 1 10.0G 1 135M 0 0 469k 0 6:12:45 0:04:54 6:07:51 1109k20000 records inserted (Tennis court) 1 10.0G 1 138M 0 0 477k 0 6:06:12 0:04:57 6:01:15 1269k20500 records inserted (Tape drive) |
Следующая часть этой главы рассказывает о регионах и некоторых других сантехнических работах.
Построить таблицу ссылок
В этой части источником является большая вики-таблица, а выходом — таблица ссылок. Каждая ссылка имеет «От:» и «Кому:». Вот ссылка на измененный рабочий скрипт: https://github.com/eyalgo/seven-dbs-in-seven-weeks/blob/master/hbase/day_2/generate_wiki_links.rb
В оставшейся части главы показано, как смотреть на данные, считать их и многое другое.
Домашнее задание
Основная часть домашней работы заключалась в создании новой таблицы: «продукты», которая берет данные из XML, который можно загрузить с сайта здравоохранения и питания США. Эти данные показывают факты питания для каждого типа пищи.
Я решил создать очень простую таблицу. Семейство столбцов не имеет специальных параметров. Я создал одно семейство столбцов: факты . Каждая строка данных из файла XML будет частью фактов. Я также решил, что ключом строки будет Display_Name . В конце концов, гораздо проще смотреть по ключу, а не по идентификатору.
|
1
|
create 'foods' , 'facts' |
Чтобы увидеть, как я должен создать скрипт, я посмотрел на два источника:
- Скрипт, который импортировал данные для таблицы Wiki
- Один элемент (еда) из XML
Вот один элемент:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<Food_Display_Row> <Food_Code>12350000</Food_Code> <Display_Name>Sour cream dip</Display_Name> <Portion_Default>1.00000</Portion_Default> <Portion_Amount>.25000</Portion_Amount> <Portion_Display_Name>cup </Portion_Display_Name> <Factor>.25000</Factor> <Increment>.25000</Increment> <Multiplier>1.00000</Multiplier> <Grains>.04799</Grains> <Whole_Grains>.00000</Whole_Grains> <Vegetables>.04070</Vegetables> <Orange_Vegetables>.00000</Orange_Vegetables> <Drkgreen_Vegetables>.00000</Drkgreen_Vegetables> <Starchy_vegetables>.00000</Starchy_vegetables> <Other_Vegetables>.04070</Other_Vegetables> <Fruits>.00000</Fruits> <Milk>.00000</Milk> <Meats>.00000</Meats> <Soy>.00000</Soy> <Drybeans_Peas>.00000</Drybeans_Peas> <Oils>.00000</Oils> <Solid_Fats>105.64850</Solid_Fats> <Added_Sugars>1.57001</Added_Sugars> <Alcohol>.00000</Alcohol> <Calories>133.65000</Calories> <Saturated_Fats>7.36898</Saturated_Fats></Food_Display_Row> |
Я создал сценарий, изучив сценарий вики и один элемент. Открытие документа происходит при обнаружении открытого тега элемента XML: Food_Display_Row . Видя Food_Display_Row как закрывающий тег, скрипт создает документ.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
include Javaimport 'org.apache.hadoop.hbase.client.HTable'import 'org.apache.hadoop.hbase.client.Put'import 'org.apache.hadoop.hbase.HBaseConfiguration'import 'javax.xml.stream.XMLStreamConstants'def jbytes( *args ) args.map { |arg| arg.to_s.to_java_bytes }endfactory = javax.xml.stream.XMLInputFactory.newInstancereader = factory.createXMLStreamReader(java.lang.System.in)document = nilbuffer = nilcount = 0puts( @hbase )conf = HBaseConfiguration.newtable = HTable.new( conf, "foods" )table.setAutoFlush( false )while reader.has_next type = reader.next if type == XMLStreamConstants::START_ELEMENT # (3) case reader.local_name when 'Food_Display_Row' then document = {} when /Display_Name|Portion_Default|Portion_Amount|Portion_Display_Name|Factor/ then buffer = [] when /Increment|Multiplier|Grains|Whole_Grains|Vegetables|Orange_Vegetables/ then buffer = [] when /Drkgreen_Vegetables|Starchy_vegetables|Other_Vegetables|Fruits|Milk|Meats/ then buffer = [] when /Drybeans_Peas|Soy|Oils|Solid_Fats|Added_Sugars|Alcohol|Calories|Saturated_Fats/ then buffer = [] end elsif type == XMLStreamConstants::CHARACTERS buffer << reader.text unless buffer.nil? elsif type == XMLStreamConstants::END_ELEMENT case reader.local_name when /Display_Name|Portion_Default|Portion_Amount|Portion_Display_Name|Factor/ document[reader.local_name] = buffer.join when /Increment|Multiplier|Grains|Whole_Grains|Vegetables|Orange_Vegetables/ document[reader.local_name] = buffer.join when /Drkgreen_Vegetables|Starchy_vegetables|Other_Vegetables|Fruits|Milk|Meats/ document[reader.local_name] = buffer.join when /Drybeans_Peas|Soy|Oils|Solid_Fats|Added_Sugars|Alcohol|Calories|Saturated_Fats/ document[reader.local_name] = buffer.join when 'Food_Display_Row' key = document['Display_Name'].to_java_bytes p = Put.new( key ) p.add( *jbytes( "facts", "Display_Name", document['Display_Name'] ) ) p.add( *jbytes( "facts", "Portion_Default", document['Portion_Default'] ) ) p.add( *jbytes( "facts", "Portion_Amount", document['Portion_Amount'] ) ) p.add( *jbytes( "facts", "Portion_Display_Name", document['Portion_Display_Name'] ) ) p.add( *jbytes( "facts", "Factor", document['Factor'] ) ) p.add( *jbytes( "facts", "Increment", document['Increment'] ) ) p.add( *jbytes( "facts", "Multiplier", document['Multiplier'] ) ) p.add( *jbytes( "facts", "Grains", document['Grains'] ) ) p.add( *jbytes( "facts", "Whole_Grains", document['Whole_Grains'] ) ) p.add( *jbytes( "facts", "Vegetables", document['Vegetables'] ) ) p.add( *jbytes( "facts", "Orange_Vegetables", document['Orange_Vegetables'] ) ) p.add( *jbytes( "facts", "Drkgreen_Vegetables", document['Drkgreen_Vegetables'] ) ) p.add( *jbytes( "facts", "Starchy_vegetables", document['Starchy_vegetables'] ) ) p.add( *jbytes( "facts", "Other_Vegetables", document['Other_Vegetables'] ) ) p.add( *jbytes( "facts", "Fruits", document['Fruits'] ) ) p.add( *jbytes( "facts", "Milk", document['Milk'] ) ) p.add( *jbytes( "facts", "Meats", document['Meats'] ) ) p.add( *jbytes( "facts", "Drybeans_Peas", document['Drybeans_Peas'] ) ) p.add( *jbytes( "facts", "Soy", document['Soy'] ) ) p.add( *jbytes( "facts", "Oils", document['Oils'] ) ) p.add( *jbytes( "facts", "Solid_Fats", document['Solid_Fats'] ) ) p.add( *jbytes( "facts", "Added_Sugars", document['Added_Sugars'] ) ) p.add( *jbytes( "facts", "Alcohol", document['Alcohol'] ) ) p.add( *jbytes( "facts", "Calories", document['Calories'] ) ) p.add( *jbytes( "facts", "Saturated_Fats", document['Saturated_Fats'] ) ) table.put( p ) count += 1 table.flushCommits() if count % 10 == 0 if count % 500 == 0 puts "#{count} records inserted (#{document['Display_Name']})" end end endendtable.flushCommits()exit |
Ниже приведены команды оболочки, которые берут файл XML и передают его в Hbase. Первая команда запускается для файла с одним элементом. После проверки правильности я запустил его до полного файла.
|
1
2
3
|
curl file:///home/eyalgo/seven-dbs-in-seven-weeks/hbase/day_2/food-display-example.xml | cat | /opt/hbase/hbase-0.94.18/bin/hbase shell /home/eyalgo/seven-dbs-in-seven-weeks/hbase/day_2/import_food_display.rbcurl file:///home/eyalgo/seven-dbs-in-seven-weeks/hbase/day_2/MyFoodapediaData/Food_Display_Table.xml | cat | /opt/hbase/hbase-0.94.18/bin/hbase shell /home/eyalgo/seven-dbs-in-seven-weeks/hbase/day_2/import_food_display.rb |
Давайте немного еды …
|
1
|
get 'foods' , 'fruit smoothie made with milk' |
И результат:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
COLUMN CELLfacts:Added_Sugars timestamp=1399932481440, value=82.54236facts:Alcohol timestamp=1399932481440, value=.00000facts:Calories timestamp=1399932481440, value=197.96000facts:Display_Name timestamp=1399932481440, value=fruit smoothie made with milkfacts:Drkgreen_Vegetables timestamp=1399932481440, value=.00000facts:Drybeans_Peas timestamp=1399932481440, value=.00000facts:Factor timestamp=1399932481440, value=1.00000facts:Fruits timestamp=1399932481440, value=.56358facts:Grains timestamp=1399932481440, value=.00000facts:Increment timestamp=1399932481440, value=.25000facts:Meats timestamp=1399932481440, value=.00000facts:Milk timestamp=1399932481440, value=.22624facts:Multiplier timestamp=1399932481440, value=.25000facts:Oils timestamp=1399932481440, value=.00808facts:Orange_Vegetables timestamp=1399932481440, value=.00000facts:Other_Vegetables timestamp=1399932481440, value=.00000facts:Portion_Amount timestamp=1399932481440, value=1.00000facts:Portion_Default timestamp=1399932481440, value=2.00000facts:Portion_Display_Name timestamp=1399932481440, value=cupfacts:Saturated_Fats timestamp=1399932481440, value=1.91092facts:Solid_Fats timestamp=1399932481440, value=24.14304facts:Soy timestamp=1399932481440, value=.00000facts:Starchy_vegetables timestamp=1399932481440, value=.00000facts:Vegetables timestamp=1399932481440, value=.00000facts:Whole_Grains timestamp=1399932481440, value=.00000 |
| Ссылка: | Семь баз данных за семь недель — Hbase Day 2 от нашего партнера по JCG Эяля Голана в блоге « Обучение и совершенствование в качестве мастера» . |