需要有效的方法在2亿行数据库(PHP)上进行简单的计算

Mar*_*ark 2 php sql database performance

我正在为以下问题请求PHP解决方案:

我在数据库中有~15个表,每个表有10-50万行,总计达到2亿行,其中列为userID,B,C,D.

我有9个其他表的列userID,fbID.每个表有大约200万行.从userID到fbID的一对一映射.

我的目标是输出这些2亿行的文件,列为fbID,B,C,D.

为了做到这一点,我必须搜索包含userID和fbID列的所有9个表,因为userID可以在一个表中找到,但不能在其他表中找到.我可以在任何一个表中找到userID后立即停止.这部分我正在使用SQL和PHP.SQL查询包括LIMIT 1,因此每当找到userID时我只返回1行,因为这些表可以包含多个具有相同userID的行.

不幸的是,这个算法需要大约60s/1k行,这需要大约130天才能完成.

有没有更有效的方法来做到这一点?

我不是数据库计算时间如何工作的专家,但我想到了一些想法:

-query遍历所有9个表,并使用userID键和fBID值创建查找表.

- 使用这9个表在数据库中创建一个新表,每个userID有一行,以及相应的FBID并搜索这个表.

这里有关于表格的更具体信息:

表总计达2亿行(每个行看起来像这样):

Column         Type        Null      Default 

dtLogTime      datetime    Yes       NULL 

iUin           int(10)     No         

B              int(10)     No

C              int(10)     No

D              int(10)     No
Run Code Online (Sandbox Code Playgroud)

索引:

Keyname   Type  Unique Packed Column    Cardinality Collation Null Comment 

dtLogTime BTREE No     No     dtLogTime 323542      A         YES  

iUin      BTREE No     No     iUin      323542      A
Run Code Online (Sandbox Code Playgroud)

其他9个表中的一个:

Column     Type        Null     Default     Comments 

dtLogTime  datetime    Yes      NULL   

iUin       int(10)     No         

vFBID      varchar(48) No    
Run Code Online (Sandbox Code Playgroud)

索引:

Keyname   Type  Unique Packed Column    Cardinality Collation Null Comment 

dtLogTime BTREE No     No     dtLogTime 2179789     A         YES  

iUin      BTREE No     No     iUin      2179789     A  
Run Code Online (Sandbox Code Playgroud)

示例代码我尝试过:

// returns FBID of iuin
function getFBID($iuin){

$query = sprintf("SELECT vFBID FROM `tbReg` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
  $row = mysql_fetch_assoc($result);
  return $row['vFBID'];
}
mysql_free_result($result);

$query = sprintf("SELECT vFBID FROM `tbOnline` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
  $row = mysql_fetch_assoc($result);
  return $row['vFBID'];
}
mysql_free_result($result);

$query = sprintf("SELECT vFBID FROM `tbConsumeFBC` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
  $row = mysql_fetch_assoc($result);
  return $row['vFBID'];
}
mysql_free_result($result);

$query = sprintf("SELECT vFBID FROM `tbFeed` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}
mysql_free_result($result);

$query = sprintf("SELECT vFBID FROM `tbInvite` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}
mysql_free_result($result);  

$query = sprintf("SELECT vFBID FROM `tbFreeGift` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}
mysql_free_result($result); 

$query = sprintf("SELECT vFBID FROM `tbUninstall` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}
mysql_free_result($result);  

$query = sprintf("SELECT vFBID FROM `tbDownload` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}

$query = sprintf("SELECT vFBID FROM `tbIUserSource` WHERE iuin = " . $iuin . " LIMIT 1");
$result = mysql_query($query);
if(mysql_num_rows($result) != 0){
   $row = mysql_fetch_assoc($result);
   return $row['vFBID'];
}
mysql_free_result($result);
}

fwrite($handle, '"Time","FBID","Action","ActionID"' . "\n");

$query = sprintf("SELECT count(dtLogTime) AS length
                  FROM `tbActionWeeding`");
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
$length = ceil($row['length'] * 0.0001);
$start = 0;
$i = 0;
while($i++ < 10000)
   $query = sprintf("SELECT dtLogTime, iuin, iWeedID
                     FROM `tbActionWeeding`
                     LIMIT " . $start . "," . $length);
   $result = mysql_query($query);
   if (!$result) {
      $message  = 'Invalid query: ' . mysql_error() . "\n";
      $message .= 'Whole query: ' . $query . "\n";
      die($message);
   }
   while($row = mysql_fetch_assoc($result))
      fwrite($handle, '"' . $row['dtLogTime'] . '","' . getFBID($row['iuin']) .
                   '","0","' . $row['iWeedID'] . "\"\n");
   mysql_free_result($result);
   $start += $length;
}
Run Code Online (Sandbox Code Playgroud)

Geo*_*ins 5

我有9个其他表的列userID,fbID

这些其他9个表每个都有大约200万行

仅使用聪明的代码就不能轻易克服这种数据结构的低效率.由于您需要处理大量冗余数据,因此最有效的算法将在此体系结构中运行缓慢.

你需要的是规范化.您应该更改表的结构以删除冗余数据.这将消除搜索9个独立表2亿次的需要,从而显着提高效率.