Эффективный способ удалить несколько строк в HBase - PullRequest
8 голосов
/ 06 января 2011

Есть ли эффективный способ удаления нескольких строк в HBase или мой вариант использования пахнет как непригодный для HBase?

Существует таблица с именем 'chart', которая содержит элементы, которые находятся в диаграммах.Ключи строк имеют следующий формат: chart|date_reversed|ranked_attribute_value_reversed|content_id

Иногда я хочу регенерировать график на определенную дату, поэтому я хочу удалить все строки, начиная с 'chart | date_reversed_1' до 'chart | date_reversed_2'.Есть ли лучший способ, чем выдать Delete для каждой строки, найденной при сканировании?Все строки, которые будут удалены, будут близки друг к другу.

Мне нужно удалить строки, потому что я не хочу, чтобы один элемент (один content_id) имел несколько записей, которые он будет иметь, если егоranked_attribute_value было изменено (его изменение является причиной, по которой диаграмма должна быть восстановлена).

Будучи новичком в HBase, так что, возможно, я мог бы неправильно использовать строки для чего-то, что столбцы будут лучше - если у вас есть дизайнпредложения, круто!Или, может быть, диаграммы лучше генерируются в файле (например, нет HBase для вывода)?Я использую MapReduce.

Ответы [ 3 ]

7 голосов
/ 07 января 2011

Во-первых, до точки удаления диапазона в HBase, AFAIK, еще нет удаления диапазона.Но есть способ удалить более одной строки за раз в HTableInterface API .Для этого просто сформируйте объект Delete с ключами строки из сканирования и поместите их в список и используйте API, готово!Чтобы ускорить сканирование, не включайте семейство столбцов в результат сканирования, поскольку все, что вам нужно, это ключ строки для удаления целых строк.

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

Для моего предположения о требовании я бы предложил использовать три таблицы - auto_id, content_charts и generate_order.Ключом строки для content_charts будет его идентификатор содержимого, а ключом строки для generate_order будет long, который будет с автоматическим уменьшением с использованием HTableInterface API .Для уменьшения используйте «-1» в качестве суммы для смещения и инициализации значения Long.MAX_VALUE в таблице auto_id при первом запуске приложения или вручную.Так что теперь, если вы хотите удалить данные диаграммы, просто очистите семейство столбцов, используя delete , затем верните новые данные и затем поместите их в таблицу generate_order.Таким образом, последняя вставка будет также в верхней части таблицы последней вставки, которая будет содержать идентификатор содержимого в качестве значения ячейки.Если вы хотите убедиться, что в Generated_order есть только одна запись для каждого содержимого, сначала сохраните идентификатор generate_order, возьмите значение и сохраните его в content_charts при установке и перед удалением семейства столбцов, сначала удалите строку из созданного заказа.Таким образом, вы можете искать и составлять графики для контента, используя максимум 2, и для графиков не требуется сканирование.

Надеюсь, это полезно.

2 голосов
/ 07 марта 2014

Я столкнулся с вашей ситуацией, и это мой код для реализации того, что вы хотите

Scan scan = new Scan();
    scan.addFamily("Family");
    scan.setStartRow(structuredKeyMaker.key(starDate));
    scan.setStopRow(structuredKeyMaker.key(endDate + 1));
try {
    ResultScanner scanner = table.getScanner(scan);


    Iterator<Entity> cdrIterator = new EntityIteratorWrapper(scanner.iterator(), EntityMapper.create(); // this is a simple iterator that maps rows to exact entity of mine, not so important ! 

    List<Delete> deletes = new ArrayList<Delete>();
    int bufferSize = 10000000; // this is needed so I don't run out of memory as I have a huge amount of data ! so this is a simple in memory buffer
    int counter = 0;
    while (entityIterator.hasNext()) {
        if (counter < bufferSize) {
                            // key maker is used to extract key as byte[] from my entity 
            deletes.add(new Delete(KeyMaker.key(entityIterator.next())));
            counter++;

        } else {
            table.delete(deletes);
            deletes.clear();
            counter = 0;
        }
    }

    if (deletes.size() > 0) {
        table.delete(deletes);
        deletes.clear();
    }

} catch (IOException e) {
    e.printStackTrace();
}
2 голосов
/ 18 февраля 2014

Вы можете использовать BulkDeleteProtocol, который использует Scan, который определяет соответствующий диапазон (начальная строка, конечная строка, фильтры).

См. здесь

...