2013-05-27 97 views
4

超過1000行的問題我有此查詢將返回我在給定區域內的所有興趣點:Doctrine2具有選擇

$query = $em 
      ->createQuery(
        'SELECT f FROM MyApplication\MyBundle\Entity\POI p 
      WHERE (p.latitude BETWEEN :southEastLatitude AND :norhtWestLatitude) AND 
        (p.longitude BETWEEN :southEastLongitude AND :norhtWestLongitude) 
      ORDER BY p.name 
    '); 

    $query->setParameter(":norhtWestLatitude", $northWestLat); 
    $query->setParameter(":norhtWestLongitude", $northWestLng); 
    $query->setParameter(":southEastLatitude", $southEastLat); 
    $query->setParameter(":southEastLongitude", $southEastLng); 

如果我嘗試用小面積訪問(與小的差異PARAMS) ,我成功得到了結果。我想我得到的結果高達1000行......我不太確定。

如果我嘗試用一​​個更大的區域來訪問,我得到一個空結果...

不知怎的,射擊與大面積的PARAMS相同的查詢,我得到正確的結果集(〜1060行)。

所以我想了解一下學說的限制(甚至Symfony的???我用我的Symfony2項目裏學說),還有什麼?我也試過$query->setMaxResults(999999999);,但它並沒有幫助...

任何人有同樣的問題?

編輯:也許PHP的內存使用率是很高?我之前和調用getResult後添加這些行:

echo "Memory usage before: " . (memory_get_usage()/1024) . " KB" . PHP_EOL; 
echo "Memory usage after: " . (memory_get_usage()/1024) . " KB" . PHP_EOL; 

輸出爲:

內存使用後:5964.0625 KB

內存使用後:10019.421875 KB

編輯: 奇怪的測試:

1)如果我與這​​些參數進行測試:

WHERE 
    (f.latitude BETWEEN 45.64273082966722 AND 47.29965978937995) AND 
    (f.longitude BETWEEN 4.93262593696295 AND 9.99999999999999) 

我得到923行(正常行爲)

2)如果我改變參數9.999999999999到10.000000000(或某些數目大於9.9999999 ),我在我的應用程序中得到一個空的結果集。 數據庫仍返回923行(爲10.000000000)。

編輯: 我能解決這個問題,這裏討論:https://groups.google.com/d/msg/doctrine-user/qLSon6m4nM4/y5vLztHcbDgJ

+1

app/logs/dev.log中的任何內容?檢查PHP錯誤日誌超過內存限制也許? – nifr

+0

可能是內存問題,並檢查相關實體是否也被拉出。 – Geshan

+0

沒有什麼有趣的記錄在app/logs/dev.log中,並且在php錯誤日誌中沒有記錄。我沒有收到任何錯誤消息,我只是得到一個空的結果集。 – eav

回答

2

從Doctrine2郵件列表中我得知你映射的屬性類型「串」:

/** @ORM\Column(name="latitude", type="string", length=255, nullable=false) */ 
private $latitude; 

/** @ORM\Column(name="longitude", type="string", length=255, nullable=false) */ 
private $longitude; 

這意味着你的數據庫將具有這些屬性的VARCHAR列。所以當數據庫運行你的查詢時,它會執行一個字符串比較。

字符串比較不同於(正常)數字比較。見這些結果:

$a = 1234567890; 
$b = 987654321; 

echo $a == $b ? '0' : ($a < $b ? '-1' : '1'); // output: 1 (means $a is bigger than $b) 

echo strcmp($a, $b);       // output: -8 (means $a is smaller than $b) 

因此,這可能是最好的性質的東西將代表數字在你的數據庫(十進制將是一個不錯的選擇)地圖:

/** @ORM\Column(name="latitude", type="decimal", nullable=false) */ 
private $latitude; 

/** @ORM\Column(name="longitude", type="decimal", nullable=false) */ 
private $longitude; 

PS:你提到你得到有效的您自己執行查詢時的結果。這可能是因爲你做的事:

... latitude BETWEEN 45.64273082966722 AND 47.29965978937995 ... 

但原則(因爲你映射屬性字符串)就可以了:

... latitude BETWEEN '45.64273082966722' AND '47.29965978937995' ... 

注意這裏的引號。這兩個語句如何處理有很大的區別,比如我的測試用例演示;)

+0

絕對正確,可以理解。問題解決了。非常感謝(也在郵件列表中的幫助) – eav

1

它可能涉及到內存使用情況。請檢查您的apache日誌是否有內存錯誤。

當選擇大量的數據,可能會有所幫助使用$query->iterate()代替$query->getResult()as pointed out in this article

要檢查您的查詢是否生成正確的SQL,您可以記錄或以其他方式輸出調用$query->getSQL()(設置參數後)的結果。將生成的SQL提供給您選擇的數據庫客戶端,以查看是否返回了所需的結果。

+0

我沒有收到內存耗盡錯誤,並且您發佈的網站主要針對批量更改。我只選擇 – eav

+1

本文的第二部分涉及選擇大量項目,這將減少您的內存使用量。我用另一種故障排除方法擴展了我的答案(檢查SQL)。 – chiborg