如何在 C++ 中优化我的查询?

Posted

技术标签:

【中文标题】如何在 C++ 中优化我的查询?【英文标题】:How to optimize my query in c++? 【发布时间】:2011-03-22 11:08:11 【问题描述】:

在我的应用程序中,我在对象列表(即对象数组)中保存了数千条记录。我喜欢根据记录中的日期、名称等特定场景来检索数据。

我的想法是,在 for 循环中,我将数据与每条记录进行比较,然后检索记录并发送给用户。

但我觉得这不是个好主意。

我需要任何建议。

问候,

卡提克

【问题讨论】:

“过早的优化是编程中万恶之源(或至少大部分)。” ——克努特。您是否在“我的应用程序”中遇到速度问题? 肯定如果我比较每条记录,那么时间复杂度会发生如何克服这个问题? 【参考方案1】:

如果您在单个字段(例如名称)上进行比较,您可以按排序顺序维护数组并使用binary search 检索每条记录。

看起来您正在按多个字段(日期、名称等)进行排序。您可以保留多个已排序的副本(使用指针,这样您就没有多个副本),然后使用它们来检索它们。将其隔离在适当的类后面,您可以随时将想法改变为另一种选择(例如内存数据库)。

也许最好的解决方案是使用不同的键保留多个地图

class MyDatabase 
  private:
    std::map<date,Record*> indexedByRecord;
    std::map<name,Record*> indexedByName;
  public:
    Record* getByName(const name& name) const;
    Record* getByDate(const date& date) const;

等等。这通常在底层使用二叉搜索树。

【讨论】:

当然,当记录数量很少时,线性搜索可能就足够了(正如 Johnsyweb 所指出的那样!)。 在我的例子中,记录的数量是巨大的。 创建多个排序的副本是不公平的。你能提供一些其他的技术来解决这个问题吗? 在这种情况下,二分搜索会将您从 O(N) 降低到 O(lg N) 比较,这可能会节省大量资金。您需要考虑保持它们的顺序和插入等有多么困难。也许使用 std::map 是最好的起点。 为什么制作指针的多个排序副本是不公平的?它一直在“现实世界”中完成...... :)【参考方案2】:

由于您还提到了 c,如果您的列表是静态的,您可以实现指针的排序数组。

    int num_records = number_of_records_in_array;
    Record **Records_by_name = malloc(sizeof(Record *)*num_records);
    Record **Records_by_date = malloc(sizeof(Record *)*num_records);

然后将每个指针分配给一条记录。

    Record **by_name = Records_by_name;
    Record **by_date = Records_by_date;

//not sure how your records are stored in memory but you need to copy a
//pointer to both by_name and by_date
    for(int i=0; i<num_records; i++)  
      *by_name = Records_array+i;
      *by_date = *by_name;
      by_name++;
      by_date++;
    

然后你必须按它们各自的字段对指针数组进行排序,剩下的就是对它们进行二进制搜索......

当我们需要通过不同字段快速查找大量数据时,我一直使用它。

【讨论】:

【参考方案3】:

您是否考虑过使用哈希表? ...您实际上可以有几个不同的哈希表,每个哈希表都存储一个指向堆上实际记录的指针,并且指针根据您要查询的数据在每个表中进行哈希处理。这将为每次查找提供恒定的复杂性(即 O(1))。

例如,您将在堆上创建一条记录并获取指向该记录的指针。然后,如果您对记录中的日期或名称感兴趣,则有两个哈希表,一个用于日期,一个用于名称。将散列函数应用于名称的记录,并根据散列函数的结果将指向该记录的指针存储在适当的表槽中。然后对存储指向原始记录的指针的单独哈希表中的日期执行相同操作,但根据日期字段进行哈希处理。然后,您应该进行一些非常快速的查找。插入也应该非常快,并且您的哈希函数也应该在恒定时间内执行(假设您有一个足够大的哈希表)。

如果您对自己制作不感兴趣,可以使用std::unordered_map 在 c++0x 中获取哈希表。否则,您可以使用std::vector&lt;std::list&lt;RECORD_TYPE*&gt; &gt; 作为基本容器,使用插入等功能制作一个基本的类包装(在使用它之前先将其调整到适当的大小......最好是一个大于记录数的素数你'重新计划插入)。

希望这会有所帮助,

杰森

【讨论】:

以上是关于如何在 C++ 中优化我的查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何优化mysql查询

如何优化显示数千条数据的长查询

如何在 MYSQL 中优化此查询?需要做啥

如何优化我的查询以更快地获得结果?

如何在where子句中使用max优化Oracle中的查询

如何在30M左右的大集合上优化mongo查询?