一、基础知识
1.Apache Doris
存储方式:列式存储,每列的数据作为一个整体存储在一起。写入操作相对复杂,需要将数据拆分到不同的列中存储。
场景:适合读取特定列的操作,如计算平均工资等聚合查询。
2.OLAP(联机分析处理)
OLTP(联机事务处理):数据量相对较小,但更新频繁。处理高并发的短小事务,保证数据的一致性和完整性,适用于日常业务操作。
OLAP(联机分析处理):数据量巨大,包含历史数据和汇总数据。高效的读操作和复杂的查询分析,适用于业务分析和决策支持。
比如,分析某段时间内的销售数据,以发现销售趋势和用户购买习惯。这些操作涉及大规模数据扫描和复杂计算,处理的是历史数据,需要高效的查询性能。
二、情景题
1.数据库接口开发
在使用 C++ 开发数据库接口时,你会如何设计一个高效的查询接口?需要考虑哪些性能和安全性问题?
安全: 防止sql注入,因为使用预编译语句,SQL 代码和数据是分离的,mysql_stmt_prepare
函数用于准备(预编译)一个 SQL 语句,该语句可以包含占位符(参数)。通过预编译,可以使语句的执行效率更高,同时也防止了 SQL 注入。
如果要预编译,就搭配mysql_stmt_execute
更适合于预编译和参数化查询的场景,具有更高的安全性和效率,来进行查询。executeQuery
更适合于简单的查询操作,不需要预编译。
std::string query = "SELECT * FROM mytable WHERE id=?";
MYSQL_STMT* stmt = mysql_stmt_init(db.getConnection());
if (mysql_stmt_prepare(stmt, query.c_str(), query.length()) != 0) {
throw std::runtime_error("mysql_stmt_prepare failed: " + std::string(mysql_stmt_error(stmt)));
}
// 绑定参数
int id = 1;
MYSQL_BIND paramBind[1];
memset(paramBind, 0, sizeof(paramBind));
paramBind[0].buffer_type = MYSQL_TYPE_LONG;
paramBind[0].buffer = &id;
if (mysql_stmt_bind_param(stmt, paramBind) != 0) {
throw std::runtime_error("mysql_stmt_bind_param failed: " + std::string(mysql_stmt_error(stmt)));
}
// 执行查询
if (mysql_stmt_execute(stmt) != 0) {
throw std::runtime_error("mysql_stmt_execute failed: " + std::string(mysql_stmt_error(stmt)));
}
异常处理: try catch,exception& e
资源管理:RAII
异步操作:提高并发
class Database {
public:
Database(const std::string& connectionString) : connectionString(connectionString) {}
void connect() {
// 连接数据库逻辑
}
void disconnect() {
// 断开数据库逻辑
}
QueryResult executeQuery(const std::string& query) {
// 执行查询逻辑,返回查询结果
}
void executeUpdate(const std::string& query) {
// 执行更新逻辑
}
private:
std::string connectionString;//包括主机地址、用户名、密码、数据库名
// 连接句柄等内部资源
};
class QueryResult {
public:
bool next() {
// 获取下一条结果逻辑
}
std::string getString(int columnIndex) {
// 获取字符串数据逻辑
}
int getInt(int columnIndex) {
// 获取整数数据逻辑
}
};
// 使用示例
int main() {
Database db("connection_string");
db.connect();
try {
QueryResult result = db.executeQuery("SELECT * FROM table");
while (result.next()) {
std::cout << result.getString(0) << std::endl;
}
} catch (const std::exception& e) {
std::cerr << "Database error: " << e.what() << std::endl;
}
db.disconnect();
return 0;
}