Qt QList在大小较大时崩溃

Qt QList在大小较大时崩溃,qt,qlist,qsqlquery,Qt,Qlist,Qsqlquery,我使用QList存储从SQL表读取的数据。这个表有100多万条记录。我需要把它们放到一个列表中,然后对列表进行一些处理 QList<QVariantMap> list; QString selectNewDB = QString("SELECT * FROM newDatabase.M106SRData"); QSqlQuery selectNewDBQuery = QSqlDatabase::database("CurrentDBConn").exec(selectNewDB);

我使用QList存储从SQL表读取的数据。这个表有100多万条记录。我需要把它们放到一个列表中,然后对列表进行一些处理

QList<QVariantMap> list;

QString selectNewDB = QString("SELECT * FROM newDatabase.M106SRData");
QSqlQuery selectNewDBQuery = QSqlDatabase::database("CurrentDBConn").exec(selectNewDB);
while (selectNewDBQuery.next())
{
    QSqlRecord selectRec = selectNewDBQuery.record();
    QVariantMap varMap;
    QString key;
    QVariant value;
    for (int i=0; i < selectRec.count(); ++i)
    {
        key = selectRec.fieldName(i);
        value = selectRec.value(i);
        varMap.insert(key, value);
    }
    list << varMap;
}
QList列表;
QString selectNewDB=QString(“从newDatabase.M106SRData中选择*);
QSqlQuery selectNewDBQuery=QSQLDABASE::database(“CurrentDBConn”).exec(selectNewDB);
while(选择newdbquery.next())
{
QSqlRecord selectRec=selectNewDBQuery.record();
QVariantMap-varMap;
QString键;
变异值;
对于(int i=0;i列表< p>内存耗尽,因为C++运行时报告它不能分配更多内存。QT容器不是问题。容器的数量限制在2 ^ 31 -1项,因为代码大小< int >代码>索引的使用。你离它不远。

至少:

  • 使用
    QVector
    而不是
    QList
    ,因为它对
    QVariantMap
    元素的开销要小得多

  • 如果查询允许,尝试保留空间:这将使内存需求几乎减半

  • 如果可以,编译64位目标

  • QVector列表;
    QString selectNewDB=QString(“从newDatabase.M106SRData中选择*);
    QSqlQuery selectNewDBQuery=QSQLDABASE::database(“CurrentDBConn”).exec(selectNewDB);
    auto const size=selectNewDBQuery.size();
    如果(大小>0)列表。保留(大小);
    while(选择newdbquery.next())
    {
    auto-selectRec=selectNewDBQuery.record();
    QVariantMap-varMap;
    对于(int i=0;i
    您可能没有足够的ram,或者更可能使用的是32位Qt构建,不能使用超过4 GB的ram。或者两者都有。就大小而言,容器本身应该能够处理超过20亿个元素

    QList
    也帮不上忙,因为在您的情况下,它可能会将每个元素存储为指针,并为实际的变量映射执行额外的堆分配。因此,您最终会有相当大的额外堆分配开销

    由于查询已经包含了大量的数据,它本身可能会消耗大量的ram

    除非禁用了pagefile,否则内存不足本身不会导致崩溃,因为它只会启动分页并破坏性能,但会继续运行,因此可能会达到32位进程的内存限制,该内存限制可能仅为2GB

    除了按照库巴在回答中的建议进行操作外,您可能还希望将查询拆分为更小的部分,并在几个查询中获得结果,而不是在可能的情况下在一个查询中获得结果,然后一次处理一个查询,从而减少查询结果使用的内存,并在完成查询后释放查询的内存


    还有一个选项是从
    QString
    保存RAM,以防有大量重复字符串。由于它是隐式共享的,所以可以有一组相同的字符串,所有这些字符串都使用相同的基础数据。您可以利用这一点,通过使用
    QSet
    来保留唯一字符串的集合,并快速检查字符串已存在。然后,不要使用查询结果中的字符串,而是使用集合中的字符串。由集合中的值复制的所有相同字符串都将重用相同的字符串数据。相比之下,您当前的方法将为每n个重复的字符串使用n个空间。

    您的RAM限制为特定大小。您是否可以看到程序使用的内存超过了计算机上安装的内存。“QList崩溃…”不,没有。类不能崩溃;崩溃的是应用程序。此外,从外观上看,QVector似乎正在崩溃;)谢谢你的建议。使用QVector没有帮助。是的,我正在使用32位Qt构建。我现在将尝试使用64位Qt构建。你需要存储
    QVariantMap
    和变体吗mselves?您需要存储冗余字段名吗?不需要。创建一个
    结构来表示表中的行,并将其存储在
    QVector
    中。然后它可能会工作。还要问自己:为什么要将所有数据从数据库移到RAM中?需要时只需查询数据库。是的,您所说的有意义。我知道d一些代码重构,我现在没有将整个结果集保存在QList/QVector中。相反,我一次只处理一条记录。谢谢你的建议。谢谢你的回复。我将尝试你建议的选项。目标计算机只有2GB的RAM空间,而且应用程序也是32位的。@medasumanth-检查最后一条我在字符串上做的添加,可能会节省额外的内存。“你要么没有足够的ram,要么更可能使用32位的Qt构建[…]“-或者只是连续内存块不够大,通常运行速度要快得多。@Frankosterfield-仍然可以选择使用虚拟内存。如果虚拟内存崩溃,则进程很可能已耗尽寻址空间。”。
    QVector<QVariantMap> list;
    
    QString selectNewDB = QString("SELECT * FROM newDatabase.M106SRData");
    QSqlQuery selectNewDBQuery = QSqlDatabase::database("CurrentDBConn").exec(selectNewDB);
    auto const size = selectNewDBQuery.size();
    if (size > 0) list.reserve(size);
    while (selectNewDBQuery.next())
    {
        auto selectRec = selectNewDBQuery.record();
        QVariantMap varMap;
        for (int i=0; i < selectRec.count(); ++i)
        {
            auto const key = selectRec.fieldName(i);
            auto const value = selectRec.value(i);
            varMap.insert(key, value);
        }
        list.append(varMap);
    }