kdb q - сохранить разделы параллельно - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть функция, которая «извлекает» (в данном случае просто создает) таблицу и сохраняет ее в новом разделе

npertable:100000;
dbname:`:partdb;

newpart:{[date]
    firstofmonth:"d"$"m"$date;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    table:`date`acc xasc table;
    partname:`$(("/" sv (string dbname;string "m"$date;enlist "t")),enlist "/");
    partname set .Q.en[dbname;table];
 };

Предположим, что для создания * 1004 требуется «много времени»* внутри функции (например, много строк).Теперь я не могу использовать этот метод в разных потоках

newpart peach 2018.03.01 2018.04.01 2018.05.01

из-за

ERROR: 'noupdate: `. `sym

, что неудивительно, потому что он, вероятно, не может асинхронно обновлять symфайл.

Можно ли вообще хранить параллельные разделы в kdb?

Спасибо за помощь

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Альтернативой является изменение логики вашей функции и разбивка ее на более мелкие шаги. Сначала я бы отделил перечисление от настройки на диске - таким образом, вы можете перечислять столбцы sym всех таблиц в главном потоке, а затем записывать перечисляемые данные на диск в потоках. Обратите внимание - это, вероятно, будет полезно только в том случае, если вы сначала распараллеливаете диск io.

npertable:100000;
dbname:`:partdb;

createTab:{[datep]
    firstofmonth:"d"$"m"$datep;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    delete date from `date`acc xasc table
    };

createPath:{[datep]
    .Q.dd[dbname;(datep;`t;`)]
    };

enumTab:{[t]
    .Q.en[dbname;t]
    };

setInParallel:{[datep]
    enummedTabs:{enumTab createTab x} each datep;
    paths:createPath each datep;
    .[set;] peach flip (paths;enummedTabs)
    };

Теперь вы можете запустить setInParallel со списком дат

bash> q code.q -s 5
q)setInParallel .z.d-til 5
`:partdb/2018.04.25/t/`:partdb/2018.04.24/t/`:partdb/2018.04.23/t/`..

Некоторые заметки, чтобы знать:

  • Вам не нужен столбец даты при установке таблицы на раздел даты. Вы, конечно, можете иметь его, но он становится виртуальным столбцом дат, когда q отображается в каталогах дат, поэтому в этом нет необходимости. Следовательно, почему я удаляю столбец даты при создании.

  • .Q.dd - очень полезная функция для создания путей (проще, чем построение строк). Обратите внимание, как я создаю путь из корня hdb, параметра даты, имени таблицы и начального `(который обозначает начальный / (то есть dir) при создании пути)

  • Функция createTab, которую я взял из вашей функции newpart. Вы приводите введенную дату к месяцу, а затем возвращаетесь к дате, чтобы получить первую дату месяца. Это может быть то, что вы ищете, но только для того, чтобы вы знали, что вы никогда не сможете установить даты, отличные от первого числа месяца, даже если введенный параметр - 2018.01.02, например.

НТН, Шон

0 голосов
/ 25 апреля 2018

РЕДАКТИРОВАТЬ - обнаружил более старую онлайн-публикацию от Kx, в которой говорится, что мой подход ниже не является хорошей идеей: «Дескриптор не должен использоваться одновременно между потоками, поскольку нет блокировки вокруг дескриптора сокета». Но я оставлю это здесь для справки

Может быть возможно (хотя я не проверял полностью) настроить отдельный процесс записи для обработки записи, затем вы перенаправляете и отправляете данные автору записи, который, в свою очередь, выполняет перечисление и запись. Что-то вроде:

{neg[h](`runThisFunc;onThisData);(neg h)[]} peach 1 2

Флеш необходим, я считаю. Более новые версии kdb могут позволять отправлять большие объемы данных через IPC, поэтому проблем не должно быть.

Опять же, я никогда не делал этого в производственных условиях, но теоретически я не могу понять, почему ты не мог.

0 голосов
/ 25 апреля 2018

Вы можете сделать это, но это зависит от того, знаете ли вы всю вселенную возможных символов перед написанием.Если, по-видимому, это какой-то идентификатор учетной записи, вы, возможно, хорошо знаете все возможные значения перед сохранением.В этом случае вы можете сначала создать вектор sym в главном потоке, а затем перенаправить запись, выполнив перечисление с помощью оператора $ , который не обновляет глобальную переменную.Например:

npertable:100000;
dbname:`:partdb;
sym:`C123`C132`C321`C121`C131;    //create sym vector
(` sv dbname,`sym) set sym;       //save sym vector in db

newpart:{[date]
    firstofmonth:"d"$"m"$date;
    table:([]date:npertable?firstofmonth+til 25;acc:npertable?`C123`C132`C321`C121`C131;c:npertable?til 100);
    table:`date`acc xasc table;
    partname:`$(("/" sv (string dbname;string "m"$date;enlist "t")),enlist "/");
    table:@[table;`acc;`sym$];    //enumerate acc column with hardcoded column name
    partname set table;           //table already enumerated, don't use .Q.en
 };

newpart peach 2018.03.01 2018.04.01 2018.05.01

Обратите внимание, что в этом случае перечисляемое имя столбца жестко закодировано - в более гибкой реализации вы можете использовать некоторую модификацию .Q.en для определения столбцов, которые требуют перечисления, и выполнить это.для всех необходимых столбцов автоматически.

Конечно, если в вашей реальной функции newpart есть вероятность добавления новых значений в поле acc, это создает большую проблему.,В идеале вы должны знать о любых новых значениях в основном потоке перед выполнением peach, поэтому вы можете добавить любые новые значения в вектор sym.

...