簡體   English   中英

使用許多一對多關系(ORM)減少MySQL中的查詢

[英]Decreasing queries in MySQL with many one-to-many relationships (ORM)

我目前正在使用基於Kohana框架構建的PHP和MySQL設計應用程序。 我正在使用內置的ORM,事實證明它非常有用。 一切正常,但我非常關心在某些頁面上運行的查詢數量。

設置
例如,有一個頁面,您可以在其中查看充滿各個部分的類別,這些部分又包含產品。 這以表格格式列出。 每個產品都有(可能)許多屬性,標志,等級定價中斷。 這必須全部在表格中表示。

有多少疑問?
就查詢而言:類別必須查詢其中的所有部分,並且這些部分必須查詢它們包含的所有產品。 還不錯,但每個產品必須查詢它的所有產品屬性,層定價和標志。 因此,向類別添加更多產品會使查詢多次增加(因為我目前主要使用ORM)。 在一個部分中有幾百個產品將導致幾百個查詢。 小問題,但仍然不好。

至今...
所有鍵都被編入索引。 我可以使用單個查詢提取所有信息(請參閱下面的編輯),但是,正如您所能想象的那樣,每個額外(例如)屬性,這將導致每個產品在多行中分布大量冗余數據,國旗等

我並不反對放棄ORM來顯示應用程序的部分並繼續使用查詢構建甚至原始SQL。

對此的解決方案實際上可能非常簡單,我現在只是對它一無所知,老實說這是一種解脫。 或許它不是。 我不確定。 如果我的任何解釋都不足以理解問題,那就問一下,我會試着給出一個更好的例子。 (編輯:給出更好的例子,見下文

雖然,旁注...但有一點可能有一些相關性:雖然我總是希望最有效地設計應用程序,但這不是一個每天會被打幾十次或幾百次的網站。 它更像是一個管理應用程序,可能不會被多個人同時使用。 我無法預見太多的重新加載,因為頁面上的大部分數據編輯都是通過AJAX完成的。 那么,如果在這個頁面上運行了幾百個查詢(當前查看的部分中有多少產品不一致),每次加載此特定頁面時,我是否應該關注多少? 只是一個想法,即便如此,如果有可能解決上述主要問題,我寧願這樣做。

非常感謝你!

編輯
基於幾個答案,似乎我沒有充分解釋自己。 所以,讓我發一個例子讓你看看發生了什么。 在這個例子之前,我還應該做兩個澄清:(1)還有一對多對多的關系,(2)你可能把我正在尋找的東西比作交叉表查詢。

讓我們簡化並說我們有3個主表:產品(product_id,product_name,product_date_added)product_attributes(product_attribute_id,product_id,value)通知(notification_id,notification_label)

和1個支點talbe:product_notifications(notification_id,product_id)

我們將列出表格中的所有產品。 在ORM中調用所有產品非常簡單。 因此,根據每個“產品”,我們會列出product_name和product_date_added。 但是,我們還需要列出所有產品屬性。 每種產品有0或更多。 我們還必須顯示產品的通知,其中還有0或更多。 所以目前,它的工作原理基本上是:

foreach ($products->find_all() as $product) //given that $products is an ORM object
{
   echo $product->product_id; //lets just pretend these are surrounded by html
   echo $product->product_name;
   foreach ($products->product_attributes->find_all() as $attribute)
   {
       echo $attribute->value;
   }
   foreach ($products->notifications->find_all() as $notification)
   {
       echo $notification->notification_label; 
   }
 }

這當然過於簡單,但這是我所說的原則。 這已經偉大工程 但是 ,正如您所看到的,對於每個產品,它必須查詢其所有屬性以獲取適當的集合或行。 find_all()函數將返回以下行的查詢結果: SELECT product_attributes.* FROM product_attributes WHERE product_id = '#' ,類似於通知。 它為每個產品進行了這些查詢。
因此,對於數據庫中的每個產品,查詢數量是該數量的幾倍。 因此,盡管效果很好,但它不能很好地擴展,因為它可能會導致數百個查詢。

如果我執行查詢以獲取一個查詢中的所有數據,則執行以下操作:

SELECT p.*, pa.*, n.*
FROM products p
LEFT JOIN product_attributes pa ON pa.product_id = p.product_id
LEFT JOIN product_notifications pn ON pn.product_id = p.product_id
LEFT JOIN notifications n ON n.notification_id = pn.notification_id

(再次過度簡化)。 這將獲取數據本身,但根據產品的每個屬性和通知,將返回帶有冗余信息的額外行。

例如,如果我在數據庫中有兩個產品; 一個有1個屬性和1個標志,另一個有3個屬性和2個標志,它將返回:

product_id, product_name, product_date_added, product_attribute_id, value, notification_id, notification_label
1, My Product, 10/10/10, 1, Color: Red, 1, Add This Product
2, Busy Product, 10/11/10, 2, Color: Blue, 1, Add This Product
2, Busy Product, 10/11/10, 2, Color: Blue, 2, Update This Product
2, Busy Product, 10/11/10, 3, Style: New, 1, Add This Product
2, Busy Product, 10/11/10, 3, Style: New, 2, Update This Product

不用說,這是一個很多冗余的信息。 每個產品返回的行數將是它擁有的通知數量的屬性數。

ORM(或者,通常只是在循環中創建新查詢)將每行中的所有信息合並到它自己的對象中,從而允許更邏輯地處理數據。 那是搖滾樂。 在一個查詢中調用信息消除了對可能數百個查詢的需要,但是在行中創建了大量冗余數據,因此不會以簡潔的集合返回(一個/多個)到多個關系數據。 那是個難點。

對不起,這么久,試圖徹底,哈哈,謝謝!

一個有趣的替代方案是使用完全獨立的模型處理您的讀取和寫入。 (命令查詢分離)。 復雜的對象模型(和ORMS)非常適合於復雜的業務行為建模,但是作為查詢和向用戶顯示信息的接口很糟糕。 你提到你並不反對放棄使用ORM渲染顯示器 - 嗯,這正是許多軟件架構師現在提出的建議。 編寫一個完全不同的界面(具有自己的優化查詢),用於讀取和報告數據。 “讀取”模型可以查詢與ORM支持的“寫入”模型一起使用的相同數據庫,也可以是針對您需要生成的報告/屏幕進行非規范化和優化的單獨數據庫。

看看這兩個演示文稿。 這可能聽起來有點矯枉過正(如果你的性能要求非常低,可能就是這樣),但是這種技術讓這么多問題消失的感覺真是太棒了。

一個好的ORM應該為你處理這個問題。 如果您認為必須手動執行此操作,則可以執行此操作。

在單個查詢中獲取所需的所有類別,並將主鍵ID存儲在PHP數組中。

運行類似這樣的查詢:

mysql_query('SELECT yourListOfFieldsHere FROM Products WHERE Product_id IN ('.implode(',', $categoryIDs).')');

這應該為您提供單個查詢中所需的所有產品。 然后使用PHP將這些映射到正確的類別並相應地顯示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM