我們的數據庫中有很多表格,其中的數據在某段時間內僅相關/有效。例如合約,它們有一個start_date和一個end_date。這不一定是整整一個月。如何建模數據/索引以快速查找時間片
現在,這是查詢對這個表的典型類型:
SELECT
*
FROM
contracts c
WHERE
c.start_date <= :1
AND c.end_date >= :2
AND c.region_id = :3
因爲我們有20個年份的數據,在我們的餐桌(〜7000天),日期是很好的過濾條件,特別是當: 1和2是同一天。 region_id並不是一個很好的過濾標準,因爲沒有那麼多(〜50)。在這個例子中,我們有(其中包括)2個索引我們的餐桌上:
contracts_valid_index (start_date, end_date)
contracts_region (region_id)
不幸的是,上面的查詢會經常我們contracts_region索引,因爲優化器認爲它更便宜。這背後的原因很簡單:當我在數據中間選擇一天時,數據庫會認爲在start_date上的索引不會很好,因爲它只會過濾掉一半的數據。通過查看end_date,同樣適用。所以優化器認爲他只能過濾掉1/4的數據。因爲他不知道start_date和end_date通常非常靠近,所以這個索引會非常有選擇性。
使用contracts_valid_index的執行計劃的成本高於使用contracts_region的執行計劃的成本。但實際上這些contracts_valid_index要好很多。
我目前不認爲我可以通過製作更好的索引來加快我的查詢速度(除了刪除除contract_valid_index外的所有內容)。但是,也許我的數據模型對查詢優化器來說不是很好。所以我假設其他人也有類似的需求,並希望知道他們是如何建模他們的數據或優化他們的數據表/索引。
有什麼建議嗎?
這就是我正在尋找的。我不喜歡開放時間間隔,但這不應該成爲問題。但我懷疑我會爲這個 – EasterBunnyBugSmasher
JPA支持我做了一些額外的研究發佈此之後,開始和結束日期列可以是日期或時間戳和空值被視爲的開始和結束時間,但如果你爲這些價值使用魔術日期,他們會繼續工作。 – Sentinel
對於開放式和封閉式的範圍,我與兩者合作,遠比偏好開放式。這樣,當一個範圍結束並且下一個開始時,您可以使用相同的日期來開始下一個開始,而不用擔心重疊。如果您在開始日期和結束日期使用截斷值,則不必擔心未截斷的範圍檢查落在一個範圍結束點和下一個開始點之間的間隔中。 – Sentinel