3

首先,我要感谢您在页面上提供的所有帮助,这真的很有帮助。现在我遇到了一个我想不通的情况,希望你能帮助我,就是这样:

在我的工作场所,我可以访问一个包含用户(姓名、姓氏、生日和其他内容)的表的 Oracle 数据库。它有 1700 万条记录,对于每条记录,我需要生成一个唯一的键(假设它是名字的 2 个首字母加上出生日期,实际上更复杂,但它是一个例子),所以对于这个键我需要检索记录,计算键,然后用键更新记录。现在超过 1700 万条记录正在杀死服务器!

所以工作的数据库是Oracle,我把数据复制到我的机器到一个MYSQL数据库中进行测试。我打算在本地测试用php进行计算,然后创建一个java应用程序来在服务器上创建密钥,但这是一个巨大的工作量!我不知道该走哪条路。简单的选择在 php 上需要 10 分钟(在 mysql 上通过命令行需要 1.49 分钟来 COUNT() 记录)

我知道最好在记录进入时计算密钥。它们以 50 万包的形式到达,但由于我刚到这里,数据已经合并,我必须处理这些记录。

那么你会建议这个可怜的灵魂做什么来完成这样的任务。我在考虑触发器或 pl/sql,但我真的不知道在性能方面什么会更好。

非常感谢你!!!

-----------作为食人魔的请求,希望你能帮助我,这是我需要为每一行做的计算的php代码

$vn=0;//holds the value calculated for name
$sql="select * from roots";//table holding triplets for character|number (ex: 1|A|13), field names (consecutive|character|code)
$resultados=mysql_query($sql,$idcon);
while($dato=mysql_fetch_array($resultados))//i put all of the pairs in an associative array for quicker acces
{
    $consulta[$dato['v_propio']]=array($dato['caracter'],$dato['v_primo']);
}
//coding the name, for every char in the name i add to $vn, the consecutive times the position of the character in the string, plus the code for the character, if null, i add some values
$pos=1;
for ($i=0;$i<strlen($nombre);$i++)
{
    $char=substr($nombre,$i,1);
    $char=charnum($char);
    if($char!=NULL)
    {
    $vn=$vn+($char*$pos)+$consulta[$char][1];
    }
    else
    $vn=$vn + 28 + 107;
    $pos++;
}
//end of name coding
// i format the code for the name to 4 digits
if ( $vn < 1000 and $vn > 99 )
    $vn = '0'.$vn ;
else if ( $vn < 100 and $vn > 9 ) 
    $vn = '00'.$vn; 
else if ( $vn < 10 ) 
    $vn = '000'.$vn; 
 else
    $vn=$vn; 

//最后,我将名称中的前两个字符与计算的代码和生日 EX:JH235408071984 将来自 JHON 出生于 1984/08/07,名称代码计算为 2354

$CODE=trim(substr($nombre,0,2)).trim($vn).formatFecha($fnac);

希望它有帮助,你可以给我一些指示!

4

2 回答 2

1

您不必使用php进行计算,首先,为您的表添加一个unique_key列,然后在该列上创建索引/唯一约束,之后您可以使用sql更新整个表一次,生成的值是一行的唯一键,计算在 SQL 中不是通过 php

update table set unique_key = generated_value

, 之后如果你想找人, 你会计算它的 unique_key 然后使用查询

select * from table where unique_key = generated_value
于 2013-02-20T05:19:11.557 回答
1

当面对像这样的庞大数据集时,我通常会做的,首先是放在某个地方来跟踪我在哪里(只需一张表就可以完成这项工作),然后一次运行 1000 个左右的结果。假设您不需要最大程度的准确度来确定将有多少记录(假设没有巨大的空洞),并且还要将数据用于我们的循环,我们可以使用像这样的查询:

SELECT MIN(ID) AS MinID, MAX(ID) AS MaxID FROM Users

假设您有一个名为 ID 的 PK 身份。与完整的 COUNT(*) 或 COUNT(1) 相比,这个查询应该非常快。然后,您可以测试我上面提到的表,以查看数据是否存在,如果不存在,则从头开始,如果存在,则从您离开的地方开始处理这些 ID。这可能需要在有这么多记录的情况下运行很长时间,但是可以这样做以使其能够根据需要重新运行,或者永远运行直到完成。

它最终会看起来像(很多伪函数,因为我不知道你将使用什么平台):

define("NUM_PER_ITERATION", 1000);

// Get our ID range
$query = "SELECT MIN(ID) AS MinID, MAX(ID) AS MaxID FROM Users";
$array = $MyDB->GetSingleRow($query);
$minid = (int) $array["MinID"];
$maxid = (int) $array["MaxID"];

// Get our last starting point
$startingpoint = LoadLastWorkPosition();
if (!$startingpoint || $startingpoint < $minid) {
  $startingpoint = $minid;
} else if ($startingpoint > $maxid) {
  echo("Already done!");
  exit;
}

// Run through the values
$curstart = $startingpoint;
while ($curstart <= $maxid) {
  $curend = $curstart + NUM_PER_ITERATION - 1;

  // Set a time out so it will keep running, you'll know way better
  // than I how long this should be for each loop
  set_time_limit(300);

  // Handle a number of results
  HandleResults($curstart, $curend);

  // Set the start of the next entry
  $curstart = $curend + 1;

  // Save our current progress
  SaveLastWorkPosition($curstart);
}

echo("All done!");

您必须设计 LoadLastWorkPosition (它尝试加载最后一个位置并返回 0 或 false 或其他任何位置,如果没有), SaveLastWorkPosition (这样您就可以跟踪您离开的位置......允许一个单独的脚本检查值以及查看进度条或跟踪的位置)和 HandleResults(加载特定范围内的 ID 并为它们创建唯一值)。

无论如何,如果没有别的,希望能帮助你开始!

于 2013-02-20T05:28:13.743 回答