C++ Apache Orc 没有正确过滤数据
C++ Apache Orc is not filtering data correctly
我正在发布一个简单的 C++ Apache orc 文件读取程序,其中:
从ORC文件中读取数据。
根据给定的字符串过滤数据。
示例代码:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
/// THIS LINE SHOULD FILTER DATA BASED ON COLUMNS.
/// INSTEAD OF FILTERING IT TRAVERSE EACH ROW OF ORC FILE.
builder->equals("column_name", orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
我尝试在 google 上搜索将近一个星期,并尝试将每个可能的 java 程序转换为 C++ 以使我的代码正常工作。
我尝试使用 中的示例,它有类似的问题但对我不起作用。
**题:**
1.我是否正确连接过滤代码。如果是,那么为什么它不根据给定的字符串过滤数据。
2. 我在哪里可以找到行级或条级过滤器的 C++ 或 'relevant Java code'。
经过多次尝试,终于解决了上述ORC数据过滤问题
这是因为使用了不正确的列号,我不确定为什么要获取的列的 column id
和要过滤的列之间存在差异。
在上面的示例中,我尝试使用 column name
过滤数据,但使用列名过滤 ORC 的问题仍然存在。但不幸的是,它在列号上工作正常。
新代码:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
// <-- HERE COLUMN IDS ARE STARTING FROM 0-N. -->
std::list<uint64_t> cols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
m_RowReaderOpts.include(cols);
int column_id = 7; // IN cols ABOVE, THIS COLUMN_ID 7 IS ACTUALLY 6. WHICH MEANS COLUMN_ID TO FILTER COLUMN IS +1 OF COLUMN ID PROVIDED IN DATA FETCH.
builder->equals(column_id, orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
根据我在解决上述问题时的理解,用于获取数据的列 ID 从 0-N 开始,用于过滤的列 ID 为 1-N。这就是为什么当您需要在 0
.
列过滤数据时,您应该提供 1
解释中的困惑:
在 ORC 中,列字段 ID 与列类型 ID 不同:
- 对于将结构作为 top-level 对象的文件,字段 ID 0 对应于第一个结构字段,字段 ID 1 对应于第二个结构字段,依此类推。在此处查看评论:https://github.com/apache/orc/blob/v1.7.3/c++/include/orc/Reader.hh#L122-L123
- 列类型id是类型树的pre-order遍历索引。正如 spec 中提到的:类型树通过 pre-order 遍历被展平为一个列表,其中每个类型都被分配了下一个 id。显然,类型树的根始终是类型 id 0。
因此,如果 ORC 文件中没有嵌套类型 (struct/array/map),我们可以在除根结构类型之外的所有列上看到 columnTypeId == columnFieldId + 1
。
构建 sargs 时使用的 ID 是列类型 ID。但是,RowReaderOptions::include(const std::list<uint64_t>& include)
中使用的 id 是列字段 id。要具有一致的 ID 映射,我建议对类型 ID 使用 include 方法:
RowReaderOptions::includeTypes(const std::list<uint64_t>& types);
我正在发布一个简单的 C++ Apache orc 文件读取程序,其中:
示例代码:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
/// THIS LINE SHOULD FILTER DATA BASED ON COLUMNS.
/// INSTEAD OF FILTERING IT TRAVERSE EACH ROW OF ORC FILE.
builder->equals("column_name", orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
我尝试在 google 上搜索将近一个星期,并尝试将每个可能的 java 程序转换为 C++ 以使我的代码正常工作。
我尝试使用
**题:**
1.我是否正确连接过滤代码。如果是,那么为什么它不根据给定的字符串过滤数据。
2. 我在哪里可以找到行级或条级过滤器的 C++ 或 'relevant Java code'。
经过多次尝试,终于解决了上述ORC数据过滤问题
这是因为使用了不正确的列号,我不确定为什么要获取的列的 column id
和要过滤的列之间存在差异。
在上面的示例中,我尝试使用 column name
过滤数据,但使用列名过滤 ORC 的问题仍然存在。但不幸的是,它在列号上工作正常。
新代码:
#include <iostream>
#include <list>
#include <memory>
#include <chrono>
// Orc specific headers.
#include <orc/Reader.hh>
#include <orc/ColumnPrinter.hh>
#include <orc/Exceptions.hh>
#include <orc/OrcFile.hh>
int main(int argc, char const *argv[])
{
auto begin = std::chrono::steady_clock::now();
orc::RowReaderOptions m_RowReaderOpts;
orc::ReaderOptions m_ReaderOpts;
std::unique_ptr<orc::Reader> m_Reader;
std::unique_ptr<orc::RowReader> m_RowReader;
auto builder = orc::SearchArgumentFactory::newBuilder();
std::string required_symbol("FILTERME");
// <-- HERE COLUMN IDS ARE STARTING FROM 0-N. -->
std::list<uint64_t> cols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
m_RowReaderOpts.include(cols);
int column_id = 7; // IN cols ABOVE, THIS COLUMN_ID 7 IS ACTUALLY 6. WHICH MEANS COLUMN_ID TO FILTER COLUMN IS +1 OF COLUMN ID PROVIDED IN DATA FETCH.
builder->equals(column_id, orc::PredicateDataType::STRING, orc::Literal(required_symbol.c_str(), required_symbol.size()));
std::string file_path("/orc/file/path.orc");
m_Reader = orc::createReader(orc::readFile(file_path.c_str()), m_ReaderOpts);
m_RowReader = m_Reader->createRowReader(m_RowReaderOpts);
m_RowReaderOpts.searchArgument(builder->build());
auto batch = m_RowReader->createRowBatch(5000);
try
{
std::cout << builder->build()->toString() << std::endl;
while(m_RowReader->next(*batch))
{
const auto &struct_batch = dynamic_cast<const orc::StructVectorBatch&>(*batch.get());
/** DO CALCULATIONS */
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
auto end = std::chrono::steady_clock::now();
std::cout << "Total Time taken to read ORC file: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms.\n";
return 0;
}
根据我在解决上述问题时的理解,用于获取数据的列 ID 从 0-N 开始,用于过滤的列 ID 为 1-N。这就是为什么当您需要在 0
.
1
解释
在 ORC 中,列字段 ID 与列类型 ID 不同:
- 对于将结构作为 top-level 对象的文件,字段 ID 0 对应于第一个结构字段,字段 ID 1 对应于第二个结构字段,依此类推。在此处查看评论:https://github.com/apache/orc/blob/v1.7.3/c++/include/orc/Reader.hh#L122-L123
- 列类型id是类型树的pre-order遍历索引。正如 spec 中提到的:类型树通过 pre-order 遍历被展平为一个列表,其中每个类型都被分配了下一个 id。显然,类型树的根始终是类型 id 0。
因此,如果 ORC 文件中没有嵌套类型 (struct/array/map),我们可以在除根结构类型之外的所有列上看到 columnTypeId == columnFieldId + 1
。
构建 sargs 时使用的 ID 是列类型 ID。但是,RowReaderOptions::include(const std::list<uint64_t>& include)
中使用的 id 是列字段 id。要具有一致的 ID 映射,我建议对类型 ID 使用 include 方法:
RowReaderOptions::includeTypes(const std::list<uint64_t>& types);