繁体   English   中英

从数据库中有效地读取给定记录ID数组的多个记录

[英]Read multiple records given array of record IDs from the database efficiently

如果您的应用程序代码中具有记录ID的数组,那么从数据库中读取记录的最佳方法是什么?

$idNumsIWant = {2,4,5,7,9,23,56};

显然,遍历每个ID,因为你做N次查询不好:

foreach ($idNumsIWant as $memID) {
    $DBinfo = mysql_fetch_assoc(mysql_query("SELECT * FROM members WHERE mem_id = '$memID'"));
    echo "{$DBinfo['fname']}\n";
}

因此,也许最好使用单个查询?

$sqlResult = mysql_query("SELECT * FROM members WHERE mem_id IN (".join(",",$idNumsIWant).")");
while ($DBinfo = mysql_fetch_assoc($sqlResult))
  echo "{$DBinfo['fname']}\n";

但是,当数组具有30,000个元素时,此方法可扩展吗?

您如何有效地解决这个问题?

最好的方法最终取决于阵列中ID的数量(您显然不希望向服务器发送50MB的SQL查询,尽管从技术上讲它可能能够轻松处理它),但是主要是关于如何处理结果行。

  • 如果ID的数量非常少(比如说数千个顶部),那么使用IN语法的带有WHERE子句的单个查询将是完美的。 您的SQL查询将足够短,可以可靠,高效,快速地传输到数据库服务器。 该方法非常适合单线程循环遍历结果记录。

  • 如果ID的数量确实很大,建议您将ID数组分成几组,然后运行多个查询,每个查询都有一组ID。 对于DB服务器而言,这可能会稍微重一些,但是在应用程序端,您可以生成多个线程,并在它们到达后立即以并行方式处理多个记录集。

两种方法都可以。

注释:对于这种情况,只要数据提取不是很大的瓶颈,就应专注于数据使用。 并配置您的应用程序!

我的想法:

就处理和磁盘读取而言,第一种方法的成本太高。

第二种方法更有效,您不必担心查询大小限制 (但仍然可以检查它)。

当我不得不处理这种情况时,我看到至少三个或四个可能的解决方案:

  • 每个id一个请求; 如您所说,这并不是很好:很多请求; 我一般不那样做
  • 使用您提出的解决方案:一个请求多个ID
    • 但是您不能使用很长的id列表来做到这一点:有些数据库引擎对可以传递IN()的数据数量有限制
    • IN()一个很大的列表可能不是很好的性能
    • 因此,我通常会像对X id的一个请求那样做,然后重复一次。 例如,要感染对应于1000个ID的数据,我可以执行20个请求,每个请求获取50个ID的数据(这只是一个示例:对您的数据库/表进行基准测试可能会很有趣,因为您的特定情况可能取决于多个因素)
  • 在某些情况下,您还可以重新考虑您的请求:也许可以通过使用某种联接来避免传递此类ID列表? (这实际上取决于您的需求,表的模式,...)

另外,为便于修改获取逻辑,我将编写一个获取ID列表并返回与ID对应的数据列表的函数。

这样,您只需以相同的方式调用此函数,就可以始终获取相同的数据,而不必担心如何获取该数据; 这将允许您在需要时更改获取方法(如果有一天找到另一种更好的方法),而又不会中断任何事情:函数的工作方式将发生变化,但是由于其接口(输入/输出)将保持不变,因此不会更改代码其余部分的内容:-)

如果是我并且in子句的值列表如此之大,我将使用存储的proc和一个包含所需值的变量,并在其中使用函数将其发送到临时表中,然后加入该表。 根据要发送的值的大小,您可能需要将其拆分为多个输入变量以进行处理。 有什么方法可以将值永久存储(如果它们经常对此进行查询)在数据库中? 用户将如何挑选出30,000个值,确定他或她不会将所有值都记录下来? 因此,可能有更好的方法基于联接和where子句查询表。

通过将字符串分成令牌来使用StringTokenizer,对于u来说,处理多个值的数据会更容易处理

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM