2010-08-05 170 views
-1

我正在處理一個數據庫,其中行數在1,000,000以上。我有我的選擇聲明,但如果我首先嚐試,我會很快耗盡內存。這裏是我的2個問題:Perl DBI取數據庫的一部分?

  1. 因爲我不知道要啓動的數據庫的確切大小,有沒有辦法找出數據庫的大小而不做使用fetchall?電腦從字面上不能支持它。

  2. 是否有任何方式來獲取說某個數據庫的塊,可能一次處理5000個,而不是爲每一行都做一個單獨的fetchrow?我剛剛完成了一項測試,並且一行一行地完成了測試,其每1000行的工作時間差不多隻有4分鐘,而老闆對於要花費近3天才能完成的程序並不看好。

這是我的代碼:

while ($i < $rows) 
{ 
    if ($i + $chunkRows < $rows) 
    { 
     for ($j = 0; $j < $chunkRows; $j++) 
     { 
      @array = $sth->fetchrow(); 
      ($nameOne, $numberOne, $numberTwo) = someFunction($lineCount,@array,$nameOne,$numberOne, $numberTwo); 
     } 
    } 
    else #run for loop for j < rows % chunkrows 
    $i = $i + $j 
} 
+0

我想拉回一排行,希望能夠減少超過一百萬個單獨行上調用fetchRow的時間。 – ThePirateSheep 2010-08-05 19:00:50

+0

你使用什麼數據庫?不同的數據庫對這個問題會有不同的答案。 – 2010-08-05 19:17:19

+0

我使用DBI,我看到的唯一提取是fetchRow()和fetchall的空構造函數。我正在尋找一個fetchRows(0,5000),其中0將作爲開始的行,5000將是要獲取的行數或沿着這些行的數據 – ThePirateSheep 2010-08-05 19:23:52

回答

0

要獲取表中的行數,你可以使用

Select count(*) from Table

要限制行數返回,這可能特定於您的數據庫。例如,MySQL有一個Limit關鍵字,它可以讓你只返回一定數量的行。這就是說,如果你拉回所有行,你可能想在這裏添加一些其他問題來具體描述你在做什麼,因爲這在大多數應用程序中並不常見。

如果你的數據庫中沒有limit可用,你可以做一些事情,比如用一個布爾值標記一列來指示一行已經被處理,然後重新運行你的查詢來限制行數,跳過那些已完成。或者記錄處理的最後一行id,然後將下一個查詢限制爲具有較大id的行。有很多方法。

+0

所以我最終通過伯爵搞亂了我的生活,這讓我的生活變得更輕鬆。我有一個選擇計數(1),只是從來沒有正確的語法。 我不相信DBI中有一個限制類型的關鍵字,這正是我正在使用的。 此外,我沒有訪問權限來更新數據庫,因爲這些數據來自外部來源。查看數據庫是如何以及如何對其進行排序的,唯一按順序(如行ID或某事)是一個時間戳,但數據庫中可能有多個相同的時間戳。我正在尋找從0開始的獲取(0,5000),並且需要5000 – ThePirateSheep 2010-08-05 18:56:54

+0

我的想法是,程序需要3天的原因是由於每個獲取都是單獨的,並且每次被調用時是我的延遲和花費的大部分時間。我不知道我是否可以盡我所能地解釋它:/ – ThePirateSheep 2010-08-05 18:58:18

+1

DBI不是數據庫,它是perl數據庫*接口*。你要查找的是查看你連接的實際數據庫服務器是否有LIMIT關鍵字。你在使用什麼數據庫服務器? 如果你不能寫入數據庫......你可以寫入一個文件嗎?查詢行,將信息寫入文件,然後處理文件中的每一行。這可能會降低內存使用量。或者,對你有權寫入的第二個表執行同樣的操作。 – GrandmasterB 2010-08-05 20:03:40

1

顯示您的fetchrow循環代碼;可能有辦法改進它,這取決於你如何調用它,以及你對數據的處理方式。

我相信大多數數據庫的數據庫驅動程序會一次從服務器獲取多行數據;你將不得不說出你正在使用哪種數據庫來獲得良好的建議。如果它確實與每一行的服務器進行通信,那麼您將不得不一次修改SQL以獲取一組行,但如何實現這一點取決於您使用的數據庫。

啊,DB2。我不確定,但我認爲你必須這樣做:

SELECT * 
FROM (SELECT col1, col2, col3, ROW_NUMBER() OVER() AS RN FROM table) AS cols 
WHERE RN BETWEEN 1 AND 10000; 

並調整每個查詢的數字,直到得到一個空的結果。顯然這個 是更多的工作在數據庫端讓它重複多次查詢;我不知道是否有DB2優化方法(即臨時表)。