Содержание этой статьи изначально было написано Пас Апичеллой.
В какой-то момент любой проект модернизации данных потребует загрузки устаревших данных. Располагая распределенным хранилищем данных в памяти, таким как SQLFire, клиенты часто спрашивают (как в этом случае) о времени загрузки, потому что они могут сидеть на 50-100 ГБ данных и не хотят ждать несколько дней. Для тех, кто не знаком с базами данных NewSQL, этот пост должен дать вам хорошее представление о том, как мы загрузили 8 миллионов строк за 88 секунд. Тест показывает, как мы сможем загрузить примерно 40 ГБ данных примерно за 1 час.
Для разработчиков Java, которым нужны идеи по ускорению больших объемов вычислений, преобразований или проверок, вы можете рассмотреть предыдущую публикацию , где SQLFire используется с Spring Batch.
В SQLFire мы используем многопоточный подход к загрузке из файла CSV. Ниже я изложил 8 шагов к стратегии загрузки с объяснением того, почему что-то было сделано.
Пожалуйста, обратите внимание:
- Это основано на SQLFire 1.0.3.
- В этой конфигурации у нас есть 2 виртуальные машины, каждая с 18 ГБ памяти, которые совместно используют один и тот же домашний каталог, а также имеют отдельные диски для своих собственных дисковых хранилищ / файлов журналов.
1. Настройте SQLFire на своем пути, как показано ниже.
http://arunma.com/2011/11/prototype-design-pattern-mindmap-and-implementation/
2. На VM1 запустите локатор, как показано ниже
sqlf locator start -J-javaagent:/export/w2-gst-cert-20a/users/swale/sqlfire/build- artifacts/linux/product- sqlf/lib/sqlfire.jar -peer-discovery-address=w2-gst-cert-21 -peer-discovery- port=41111 -client-bind- address=w2-gst-cert-21 -client-port=1527 -dir=/w2-gst-cert- 21a/users/papicella/locator &
3. На VM1 и VM2 запустите 2 узла сервера SQLFire, как показано ниже.
Эти серверы имеют 18G памяти. VM2 — то, где процесс локатора был начат. Вывод ниже просто показывает, какие скрипты вам нужны для запуска этих серверов.
[Thu Jul 12 21:24:47 papicella@:~/pas/demo/load-demo ] $ cat start-server-w2-gst-cert-20.sh sqlf server start -J-javaagent:/export/w2-gst-cert-20a/users/swale/sqlfire/build-artifacts/linux/product- sqlf/lib/sqlfire.jar -server-groups=MYGROUP -initial-heap=8024m -max-heap=8024m -locators=w2- gst-cert- 21[41111] -client-bind-address=w2-gst-cert-20 -client-port=1527 -dir=/w2-gst-cert-20a/users/ papicella/server1 & [Thu Jul 12 21:27:19 papicella@:~/pas/demo/load-demo ] $ cat start-server-w2-gst-cert-21.sh sqlf server start -J-javaagent:/export/w2-gst-cert-20a/users/swale/sqlfire/build-artifacts/linux/product- sqlf/lib/sqlfire.jar -server-groups=MYGROUP -initial-heap=8024m -max-heap=8024m -locators=w2- gst-cert-21[41111] -client-bind-address=w2-gst-cert-21 -client-port=1528 -dir=/w2-gst-cert-21a/users/ papicella/server2 &
4. Создайте хранилище дисков, используя SQL, как показано ниже.
CREATE DISKSTORE STORE1 WRITEBUFFERSIZE 19292393;
5. Установите глобальную политику выселения для таблиц в группе «MYGROUP».
call sys.set_eviction_heap_percentage_sg (85, 'MYGROUP');
6. Создайте таблицу, как показано ниже.
Мы используем отдельное хранилище на диске для сохранения, и любые данные переполнения будут просто удалены из памяти и не будут записаны на диск, так как сохранение включено здесь. Эта таблица будет асинхронно записывать свои изменения в хранилище дисков, так что ей нужно только выполнить вставку в память, прежде чем перейти к следующему изменению.
drop table emp; CREATE TABLE emp (empno integer NOT NULL primary key, ename varchar(20), hiredate date, deptno int ) SERVER GROUPS (MYGROUP) EVICTION BY LRUHEAPPERCENT EVICTACTION OVERFLOW PARTITION BY COLUMN (empno) REDUNDANCY 1 PERSISTENT 'STORE1' ASYNCHRONOUS;
7. Предварительно создайте блоки, готовые для загрузки данных, запустив SQL, как показано ниже.
Если этого не сделать, то это будет сделано в первый раз, когда происходит вставка, когда SQLFire автоматически не создает сегменты.
call sys.create_all_buckets('APP.EMP');
Примечание. Это можно сделать после загрузки, как показано ниже.
call sys.rebalance_all_buckets()
8. Запустите сценарий для загрузки данных, показывающих, что вывод данных занял 88 секунд для загрузки 8 миллионов строк в кластер из 2 узлов.
В этом примере мы загружаем CSV-файл с именем «EMP.dat», который содержит 8 миллионов строк с данными, как показано ниже, и размер диска 371M.
Пример:
1,LkrpCkpGQpsUvZrFWAic,2012-02-29 05:35:10,2288856 2,gfbuiiWcUxoDOgeHuth,2012-01-10 12:57:18,1243600 3,GnR,2012-03-04 20:47:06,1533872 4,uxaGakuW,2012-03-17 20:57:34,2451659 5,coIrAvnPtvOZJirnea,2012-01-29 15:36:20,3731769 6,FJvnIjy,2012-03-24 07:37:59,4137455 7,rjnWsfbLldRtUSBDdZew,2012-01-24 13:09:22,3416189 8,DpbvPBkalbuZbBItgoJp,2012-03-28 13:41:56,6497992 9,jaba,2012-01-30 00:56:13,151525 10,EkDdiPeHBn,2012-04-02 12:05:25,630473 .....
«EMP.dat» существует только на VM2, поэтому нам нужно убедиться, что мы подключаемся только к этому узлу сервера SQLFire, и убедиться, что он единственный, ответственный за нагрузку, поскольку EMP.dat существует только на этом сервере. Для этого мы используем load-balance = false и используем read-timeout = 0, чтобы гарантировать, что клиент не остановится, если загрузка займет больше 5 минут.
скрипт loadEmp.sh
sqlf <<! connect client 'w2-gst-cert-21:1528;load-balance=false;read-timeout=0'; ELAPSEDTIME on; call syscs_util.import_table_ex('APP' /* schema */, 'EMP' /* table */, '/w2-gst-cert-21a/users/papicella/data/EMP.dat' /* file path as seen by server */, ',' /* field separator */, NULL, NULL, 0, 0 /* don't lock the table */, 6 /* number of threads */, 0, NULL /* custom class for data transformation or NULL to use the default inbuilt Import class */, NULL); !
Примечание. Количество потоков, установленных на 6, более чем достаточно. Повышение этого значения может иметь отрицательный эффект. Шесть — идеальное количество для многопоточных нагрузочных испытаний.
[Thu Jul 12 19:03:23 papicella@:/w2-gst-cert-21a/users/papicella/data ] $ ./loadEMP.sh sqlf version 10.4 sqlf> sqlf> sqlf> > > > > > > > > > > Statement executed. ELAPSED TIME = 88324 milliseconds sqlf> [Thu Jul 12 19:04:58 papicella@:/w2-gst-cert-21a/users/papicella/data ] $
Наконец, выполните запрос, как показано ниже, чтобы показать, что данные действительно были загружены и какова нагрузка на хранение 8 000 000 строк в системе для обоих узлов с точки зрения памяти.
sqlf> select sqlentity, memory, substr(id, 1, 50) "Id" FROM sys.memoryAnalytics -- SQLFIRE-PROPERTIES sizerHints=withMemoryFootPrint; SQLENTITY |MEMORY |Id ------------------------------------------------------------------------------------------------------------------------------ APP.EMP (Entry Size, Value Size, Row Count) | 832000000,204019274,8000000 | w2-gst-cert-21(10674)<v2>:2810/48871 APP.EMP (sqlfire,gemfire,others) | 241842808,229176368,196449984 (667469160 = 636.55 mb) | w2-gst-cert-21(10674)<v2>:2810/48871 APP.EMP (Entry Size, Value Size, Row Count) | 832000000,204019274,8000000 | w2-gst-cert-20(8550)<v1>:35007/36633 APP.EMP (sqlfire,gemfire,others) | 277524448,262689608,225528376 (765742432 = 730.27 mb) | w2-gst-cert-20(8550)<v1>:35007/36633 4 rows selected ELAPSED TIME = 149673 milliseconds sqlf>
Дополнительная информация
А. Ряд накладных
В настоящее время накладные расходы SQLFire для постоянной записи составляют около 100 байт, что увеличивает накладные расходы на 800 млн. Для 8 000 000 строк. Это необходимо учитывать при попытке определить объем памяти для таблиц при использовании постоянства.
B. Количество потоков для загрузки
При использовании syscs_util.import_table_ex лучше не использовать более 6 потоков для загрузки. Преимущество не увеличится, если вы добавите больше потоков, чем 6. В приведенном ниже примере просто используется 6 потоков для загрузки данных в SQLFire, что является наиболее эффективным способом.
sqlf < connect client 'w2-gst-cert-21:1528;load-balance=false;read-timeout=0'; ELAPSEDTIME on; call syscs_util.import_table_ex('APP' /* schema */, 'EMP' /* table */, '/w2-gst-cert-21a/users/papicella/data/EMP.dat' /* file path as seen by server */, ',' /* field separator */, NULL, NULL, 0, 0 /* don't lock the table */, 6 /* number of threads */, 0, NULL /* custom class for data transformation or NULL to use the default inbuilt Import class */); !
C. Подключение в качестве клиента, где существует файл данных
В приведенном ниже примере мы гарантируем, что длительно работающие клиенты нагрузки не истекают. По умолчанию время ожидания истекает через 5 минут, поэтому во избежание использования read-timeout = 0 для атрибута строки подключения. В то же время мы хотим выполнить загрузку только с одного клиента, где существует файл данных. В этом случае мы обеспечиваем подключение к клиенту, на котором существует файл данных, и отключаем балансировку нагрузки, чтобы другой узел также не пытался прочитать файл.
sqlf < connect client 'w2-gst-cert-21:1528;load-balance=false;read-timeout=0'; ELAPSEDTIME on; call syscs_util.import_table_ex('APP' /* schema */, 'EMP' /* table */, '/w2-gst-cert-21a/users/papicella/data/EMP.dat' /* file path as seen by server */, ',' /* field separator */, NULL, NULL, 0, 0 /* don't lock the table */, 6 /* number of threads */, 0, NULL /* custom class for data transformation or NULL to use the default inbuilt Import class */);