Как обновить локальную таблицу удаленно? - PullRequest
1 голос
/ 10 апреля 2019

У меня есть большая таблица на удаленном сервере с неизвестным (миллионы) количеством строк данных.Я хотел бы иметь возможность извлекать данные в пакетах по 100 000 строк за раз, обновлять мою локальную таблицу этими выбранными строками и завершать это до тех пор, пока не будут выбраны все строки.Есть ли способ, чтобы я мог обновить локальную таблицу удаленно?

В настоящее время у меня есть фиктивная таблица с именем t на сервере вместе со следующими переменными ...

t:([]sym:1000000?`A`B`Ab`Ba`C`D`Cd`Dc;id:1+til 1000000)
selector:select from t where sym like "A*"
counter:count selector
divy:counter%100000
divyUP:ceiling divy

и нижеуказанная функция на клиенте вместе с переменными indexустановите 0 и normTable, что является копией удаленной таблицы ...

index:0
normTable:h"0#t"

batches:{[idx;divy;anty;seltr]
    if[not idx=divy;
    batch:select[(anty;100000)] from seltr;
    `normTable upsert batch;
    idx+::1;
    divy:divy;
    anty+:100000;
    seltr:seltr;
    batches[idx;divy;anty;seltr]];
    idx::0}

Я вызываю эту функцию с помощью следующей команды ...

 batches[index;h"divyUP";0;h"selector"]

Проблемаоднако при таком подходе h"selector" извлекает все строки данных одновременно (и несколько раз - для каждой партии из 100 000, которые он переносит в мой локальный normTable).

Я мог бы переместить batches для удаленного сервера, но как мне тогда обновить локально normTable удаленно?

В качестве альтернативы я могу разбить строки на пакеты на сервере, а затем вытащить каждую партию отдельно.Но если я не знаю, сколько строк, как узнать, сколько переменных требуется?Например, следующее будет работать, но только до первых 400 тыс. Строк ...

batch1:select[100000] from t where symbol like "A*"
batch2:select[100000 100000] from t where symbol like "A*"
batch3:select[200000 100000] from t where symbol like "A*"
batch4:select[300000 100000] from t where symbol like "A*"

Есть ли способ установить переменную batchX, чтобы она создавала новую переменную, равную количествуdivyUP

Ответы [ 3 ]

3 голосов
/ 10 апреля 2019

Я бы предложил несколько изменений, когда вы пытаетесь подключиться к удаленному серверу:

  • Не запускайте синхронный запрос, поскольку это заставит сервер замедлить его обработку.Попробуйте сделать асинхронный запрос, используя обратные вызовы .
  • . Не выполняйте полное сканирование таблицы (для тщательного сравнения) в каждом вызове специально для регулярных выражений.Вполне возможно, что большая часть данных будет доступна в кеше при следующем вызове, но все же это не гарантируется, что опять-таки повлияет на нормальные операции сервера.
  • Не выполнять запросы данных в пакете.Либо используйте таймер, либо сделайте другой запрос данных, когда поступят последние данные пакета.

Нижеприведенный подход основан на приведенных выше предложениях.Это позволит избежать сканирования полной таблицы для столбцов, отличных от столбца индекса (что является небольшим весом), и выполнять следующий запрос только при поступлении последней партии.

Создать функцию обработки партии

Эта функция будет запускаться на сервере и считывать небольшой пакет данных из таблицы с использованием индексов и возвращать необходимые данные.

q) batch:{[ind;s] ni:ind+s; d:select from t where i within (ind;ni), sym like "A*"; 
                  neg[.z.w](`upd;d;$[ni<count t;ni+1;0]) }

Требуется 2 аргумента - начальный индекс и размер пакета для работы.

Эта функция, наконец, будет вызывать upd функцию на локальном компьютере Macintosh и передаст 2 аргумента.

  • Индекс таблицы для запуска следующей партии (возвращает 0, если все строки выполнены, чтобы остановить обработку следующей партии)
  • Данные из текущего запроса партии

Создать функцию обратного вызова

В эту функцию войдет результат от функции пакетной обработки.

Если индекс> 0, это означает, что есть еще данные для обработки, и следует запустить следующую партиюсформировать этот индекс.

q) upd:{[data;ind] t::t,data;if[ind>0;fetch ind]}

Создать основную функцию для запуска процесса

q)fetch:{[ind] h (batch;ind;size)}

Окончательно открыть соединение, создать переменную таблицы и запустить функцию fetch.

q) h:hopen `:server:port
q) t:()
q) size:100
q) fetch 0

Теперь вышеуказанный метод основан на предположении, что таблица сервера является статической.В случае, если он получает обновления в режиме реального времени, тогда потребуются изменения в зависимости от того, как таблица обновляется на сервере.

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

1 голос
/ 10 апреля 2019

Вместо того, чтобы иметь отдельные переменные, функция вырезания может разбить результат выбора на куски по 100000 строк.Индексирование каждого элемента представляет собой таблицу.

batches:100000 cut select from t where symbol like "A*"
1 голос
/ 10 апреля 2019

Если вы нормально отправляете синхронизирующие сообщения, это можно упростить до:

{[h;i]`mytab upsert h({select from t where i in x};i)}[h]each 0N 100000#til h"count t"

И вы можете легко изменить его, чтобы контролировать количество партий (а не размер), вместо этого используя 10 0N# (это будет сделано в 10 партиях)

...