我有一個DB結構,旨在以一種容易擴展的方式存儲特定對象的屬性。
有一個「對象」表。MySQL優化過濾鍵值對作爲記錄
+----+----------------------
| id | ....(name, type, etc)
+----+----------------------
接下來,我有一個「屬性」表。
+----+------+
| id | Name |
+----+------+
最後,一個「關係」表,用於保持所有與對應的值的數據作爲屬性對象對(作爲主鍵)。
+--------+---------+-------+
| id_obj | id_attr | value |
+--------+---------+-------+
我需要爲一次滿足幾個條件的對象獲取ID。例如,我擁有名爲「Type」和「City」的屬性,我需要爲這些屬性的對應值爲「Apartment」和「City b」的對象獲取ID。
我管理的最佳解決方案拿出敲打我的頭靠在牆上,因爲經過昨日(當然,這個查詢的唯一好處是,它的實際工作,並獲取所需的記錄):
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE objects.id
IN (
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE attributes.name = 'Type' AND relations.value = 'Apartment'
)
AND objects.id
IN (
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE attributes.name = 'City' AND relations.value = 'City b'
)
GROUP BY objects.id ASC
LIMIT 0 , 20
問題是,存儲的數據量可能會變得有些大,我擔心所有這些子查詢(可能需要指定10-15個過濾器),每個解析整個數據庫可能會導致嚴重的性能問題(並不是說即使使用我有限的SQL技能,我也確信必須有更好的方式來做我需要做的事情)。
另一方面,數據庫的劇烈變化並不是一個真正的選擇,因爲使用它的代碼在很大程度上取決於當前的數據庫結構。
有沒有一種方法來檢查屬性的方式,我需要它在一個單一的查詢,有限的數量或沒有更改存儲的數據結構?
工作查詢,相當於以上,但更好的一個優化,學分DRapp:
SELECT STRAIGHT_JOIN
rel.id_obj
from
relations rel
join attributes atr
on rel.id_attr = atr.id
where
(rel.value = 'Apartment' AND atr.name = 'Type' )
or (rel.value = 'City b' AND atr.name = 'City')
group by
rel.id_obj
having
count(*) = 2
limit
0, 20
謝謝!我知道我必須獲得滿足至少一項標準的所有記錄,然後以某種方式獲得滿足所有標準的記錄,但我不確定如何完全做到這一點。 STRAIGHT_JOIN選項是否通過將更小的「屬性」表中的數據連接到更大的表,從而使MySQL更高效地工作? – havelock
我在原始問題中添加了適用於我的數據庫的查詢版本。 – havelock
@Havelock,對不起,以前沒有回覆。 STRAIGHT_JOIN可以提供幫助,但是您真的需要知道查詢中的數據和最佳引導表,以獲得您想要的最小結果......例如,不要使用鏈接到數百萬記錄表的查找表。尋找能力較小/索引元素的標準。 – DRapp