Для выполнения цикла в огромном списке или словаре

Я делаю исследовательский проект по поисковым системам, и у меня проблемы с производительностью цикла for. У меня есть следующая проблема:

for value in hash_array.keys():  
        cell= db_conn.use_client().hql_query(db_conn.use_namespace(),'SELECT doc_text FROM SE_doc_text WHERE ROW=\"'+
                             value+"\" SCAN_AND_FILTER_ROWS LIMIT 1").cells  
        list_result[value].append(cell[0].value)

Используя hypertable, я хочу иметь лучшую производительность, но когда я использую ее на 20.000 или 30.000 элементах hash_array.keys(), я получаю результат, например, 5-6 минут, так что это очень медленно. Любой другой способ выполнить пост для? или я должен использовать свой план б для всей поисковой системы.

Выполнение запроса:

  Elapsed time:  0.10 s
Avg value size:  1428.00 bytes
  Avg key size:  57.00 bytes
    Throughput:  595190.38 bytes/s
   Total cells:  1
    Throughput:  400.80 cells/s

Проверено на оборудовании:

8gb 1600mhz
1055t amd

Дополнительные факты:

 Without SCAN_AND_FILTER_ROWS: 1.78163504601ms
 With SCAN_AND_FILTER_ROWS: 3.27163504601ms
 Only for loop: 0.0630ms

С решением (из ответа) у меня есть следующее:

stringRow = ' AND '.join(["ROW = \""+value + "\"" for value in hash_array.keys()])
cell = db_conn.use_client().hql_query(db_conn.use_namespace(),stringBatch+stringRow).cells  

Results:  0.355320930481ms for 2097 documents
          1.0214779377 for 3565 documents

Это хорошо, но это не лучшее решение.

2 ответа

Решение

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

Это явная оптимизация для случая, когда вы запрашиваете очень большое количество интервалов строки (например, 10000+). Вместо того, чтобы извлекать каждый интервал строк независимо, эта опция заставит систему выполнить полное сканирование таблицы и отфильтровать результаты, чтобы найти нужные строки. Используйте эту опцию с осторожностью, она может быть крайне неэффективной для меньшего количества интервалов строки.

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

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

| '(' [row_key relop] ROW relop row_key
      (OR [row_key relop] ROW relop row_key)* ')'

Итак, создайте запрос с дизъюнкцией, скажем, из 100 отдельных ключей: ROW=x OR ROW=y OR...,

Пожалуйста, не используйте для этого SCAN_AND_FILTER_ROWS, это вызывает проблемы с производительностью, когда вы просто выбираете одну строку.

Несколько способов сделать это быстрее:

  • Создайте TableScanner и добавьте несколько строк в ScanSpec, чтобы избежать накладных расходов на отправку большого количества небольших сетевых сообщений (это то, что предложил Даниэль Реншоу)
  • если ваши ключи строки находятся в диапазоне, то вы также можете получить диапазон ключей строки
  • если ваши ключи строк имеют общий префикс, то вы можете использовать поиск префикса (WHERE ROW =^ "prefix")
Другие вопросы по тегам