【问题标题】:How can I speed up loading from a sqlite database? (sqlite3_step is very slow)如何加快从 sqlite 数据库的加载速度? (sqlite3_step 很慢)
【发布时间】:2017-04-09 03:03:24
【问题描述】:

我可能有大约 1,000,000 行要加载到 C++ 对象中(通过大约 10,000 次选择)。我已经分析了负载,并注意这里的 sqlite3_step 语句是瓶颈。

sqlite3_stmt *stmt;
std::string symbol = stock->getSymbol();
boost::format sql("SELECT date,open,high,low,close,volume FROM Prices WHERE symbol=\"%s\" ORDER BY date DESC");
sql % symbol;

if (sqlite3_prepare_v2(databaseHandle_, sql.str().c_str(), -1, &stmt, NULL) == SQLITE_OK) {
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        int date = sqlite3_column_int(stmt, 0);
        float open = sqlite3_column_double(stmt, 1);
        float high = sqlite3_column_double(stmt, 2);
        float low = sqlite3_column_double(stmt, 3);
        float close = sqlite3_column_double(stmt, 4);
        int volume = sqlite3_column_int(stmt, 5);
        Price *price = new Price(new Date(date), open, close, low, high, volume);
        stock->add(price);
    }
} else {
    std::cout << "Error loading stock" << std::endl;
}

我正在使用合并的 sqlite.h/c 版本 3.15.0。有什么想法可以提高性能吗?

更多信息:

CREATE TABLE Prices (symbol VARCHAR(10) NOT NULL, date INT(11) NOT NULL, open DECIMAL(6,2) NOT NULL, high DECIMAL(6,2) NOT NULL,low DECIMAL(6,2) NOT NULL, close DECIMAL(6,2) NOT NULL, volume INT(10) NOT NULL, PRIMARY KEY (symbol, date))

CREATE INDEX `PricesIndex` ON `Prices` (`symbol` ,`date` DESC)

EXPLAIN QUERY PLAN SELECT * FROM Prices WHERE symbol="TSLA" ORDER BY date DESC;

返回

SEARCH TABLE PRICES USING INDEX PricesIndex (symbol=?)

进一步说明:如上所示的此类 SELECT 在 Mac 的 SQLite 浏览器中执行 SQL 需要 2 毫秒。

【问题讨论】:

  • 如果您关心性能,为什么要动态分配PriceDate
  • 我在某处听说,如果你为你的行建立索引会有所帮助,但这只是在黑暗中的一个镜头 :) 看起来你通常需要加速你的数据库,因为你的代码几乎没有什么都没有(假设你的构造函数并不昂贵)
  • @VittorioRomeo 这真的会降低性能吗?
  • @Rakete1111:它肯定比堆栈分配(或 emplacement) 慢。此外,它会扼杀数据局部性。
  • 我可以看到一些额外的缓存未命中,但与 SQL 的强大功能相比应该是微不足道的。

标签: c++ performance sqlite


【解决方案1】:

您的索引已经加快了搜索匹配行的速度,并以正确的顺序返回它们,因此不需要单独的排序步骤。

但是,数据库仍然需要为每个索引条目查找相应的表行。 您可以通过在所有使用的列上创建 covering index 来加速此特定查询:

CREATE INDEX p ON Prices(symbol, date, open, high, low, close, volume);

但与其复制索引中的所有数据,不如将此表设为clustered index

CREATE TABLE Prices (
    symbol VARCHAR(10) NOT NULL,
    date INT(11) NOT NULL,
    open DECIMAL(6,2) NOT NULL,
    high DECIMAL(6,2) NOT NULL,
    low DECIMAL(6,2) NOT NULL,
    close DECIMAL(6,2) NOT NULL,
    volume INT(10) NOT NULL,
    PRIMARY KEY (symbol, date)
) WITHOUT ROWID;

【讨论】:

  • 谢谢。我现在正在尝试这个。将表设为聚集索引后,我还需要原始索引还是覆盖索引?
  • 否;他们永远不会被使用。
猜你喜欢
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-08
相关资源
最近更新 更多