2010-11-18 28 views
0

我的環境的簡短說明:學說:leftJoin上表產生不必要的查詢

  • 的Symfony:1.4.8
  • 學說:1.2.3
  • Centos的5.5(PHP 5.3.3)
  • MySQL的52年5月1日

我已經建立在Symfony的一個新項目,這裏的項目模式:

# Car 
RjCar: 
    actAs: { Timestampable: ~ } 
    columns: 
    id: { type: integer(4), unsigned: true, primary: true, autoincrement: true } 
    year: { type: integer(2), unsigned: true, notnull: true } 
    engine_mod: { type: string(1000) } 
    exterior_mod: { type: string(1000) } 
    suspension_mod: { type: string(1000) } 
    audio_mod: { type: string(1000) } 
    vote_pos: { type: integer(4), notnull: true, unsigned: true, default: 0 } 
    vote_neg: { type: integer(4), notnull: true, unsigned: true, default: 0 } 
    views: { type: integer(4), notnull: true, unsigned: true, default: 0 } 
    # Foreign keys 
    category_id: { type: integer(1), unsigned: true, notnull: true } 
    category_check: { type: boolean, notnull: true, default: 0 } 
    user_id: { type: integer(5) } 
    relations: 
    RjCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: RjCars } 
    sfGuardUser: { onDelete: CASCADE, local: user_id, foreign: id, foreignAlias: RjCars } 

# Category 
RjCategory: 
    columns: 
    id: { type: integer(1), unsigned: true, primary: true, autoincrement: true } 
    name: { type: string(255), notnull: true} 

# I do not include the sfGuardUser schema, but it's the default one from the plugin 

當我想和類別名稱和用戶名檢索最後10輛汽車,我用在RjCarTable.class.php下面的代碼:

$last_cars = $this->createQuery('car') 
       ->leftJoin('car.sfGuardUser user') 
       ->leftJoin('car.RjCategory categ') 
       ->orderBy('car.created_at DESC') 
       ->limit(10) 
       ->execute(); 

    return $last_cars; 

在我的網頁一切正常,我已經所有我的結果,但在調試欄中,我看到22個查詢(而不是2)。

這裏是第一個是正常的查詢輸出:

SELECT 
/* Everything about the car */ 
r.id AS r__id, 
r.year AS r__year, 
r.engine_mod AS r__engine_mod, 
r.exterior_mod AS r__exterior_mod, 
r.suspension_mod AS r__suspension_mod, 
r.audio_mod AS r__audio_mod, 
r.vote_pos AS r__vote_pos, 
r.vote_neg AS r__vote_neg, 
r.views AS r__views, 
r.type_id AS r__type_id, 
r.category_id AS r__category_id, 
r.category_check AS r__category_check, 
r.user_id AS r__user_id, 
r.created_at AS r__created_at, 
r.updated_at AS r__updated_at, 
/* ... hidden because irrelevant... retrieve everything about the sfGuardUser and profile... */ 
/* Everything about the category */ 
r2.id AS r2__id, 
r2.name AS r2__name, 
FROM rj_car r 
LEFT JOIN sf_guard_user s ON r.user_id = s.id 
LEFT JOIN rj_category r2 ON r.category_id = r2.id 
ORDER BY r.created_at DESC 
LIMIT 10 

所以在那之前一切正常,除了這個查詢被20人以獲取有關每個類別的信息(2個查詢每個結果很明顯),而在前面的查詢中可以注意到這些信息是可用的。我不會把所有的人,但這裏是一些:

SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '8') LIMIT 1 
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '8') LIMIT 1 
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '9') LIMIT 1 
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '9') LIMIT 1 
/* etc.. 20 times */ 

所以我的真正的問題是: - 爲什麼執行所有這些不必要的查詢,而第一個查詢應該有這些信息? - 爲什麼sfGuardUser表不會發生這種情況?我的RjCar對象和sfGuardUser對象之間的關係顯然與RjCar和RjCategory之間的關係相同。

如果有人已經面臨同樣的問題,我會很高興聽到它。正如我所說的一切工作正常,但我prefere這個模塊不會產生不必要的查詢,因爲它應該在我的應用程序的主頁上執行。

回答

0

我拍了拍自己:

以下是我在RjCar.class.php發現

/** 
* Return the category of the car 
*/  
public function getRjCategory(){ 
    return Doctrine_Core::getTable('RjCategory')->find($this->getCategoryId()); 
} 

所以這解釋了不必要的查詢......我甚至不記得寫這一塊代碼,但考慮到我是唯一一個在這個項目上工作的人,我想這是我的。

像往常一樣,問題是椅子和鍵盤之間...

感謝您的幫助。

-1

當使用像Doctrine和Hibernate這樣的ORM框架時,它經常會產生冗餘和難看的查詢。查詢越複雜,它在這些系統上的醜陋(嘗試爲連接的查詢添加一個「限制」並查看生成的代碼)。
框架通常爲您的案例的80%提供很好的解決方案。對於剩餘的20%,你需要稍微努力工作。通常這是一個公平的權衡。
如果您擔心此查詢的輸出質量,或者認爲您無法負擔其導致的延遲 - Doctrine具有用於編寫和管理自定義查詢的非常簡單的方法。不要害怕走上這條路......

+0

雖然你是正確的,有時有必要打破ORM,這絕對不是案件之一。 – 2010-11-19 00:19:52

0

這種行爲似乎很奇怪,絕對不是預期的。有些事情可以嘗試:

  • 你在緩存原則查詢或結果嗎?有時,查詢可能會在奇怪效果更改模型後保持緩存。
  • 這些查詢看起來很像學說的懶惰行爲。您是否試圖縮小哪些調用具體觸發這些查詢?嘗試追蹤哪些特定的行觸發查詢,並查看它們是否有特殊之處。
+0

感謝您的關注。我認爲它沒有被緩存:我每次使用doctrine:build --all - and-load命令,接下來是cc。如果我從查詢中刪除 - > leftJoin('RjCategory'),那麼一切都很好。但是,由於暗示加載的提示,我沒有想到這一點。 – Remiz 2010-11-19 03:28:00