我有一個功能基礎上的名字,這是不是唯一的一個迴歸人的身份證。爭論是姓氏,名字和組織; firstname參數可以是名稱,首字母或NULL。這裏是採摘同名的一個(功能init()
返回一個字符串後跟一個fulstop的第一個字母)鍵查詢:幾個ORDER BY條件,最後一個昂貴 - 如何優化它?
SELECT p.id INTO _p FROM person p
WHERE p.lastname = _lastname AND (_firstname IS NULL
OR inic(p.firstname) = _inic)
ORDER BY (p.firstname = _firstname) DESC, (p.organization = _org) DESC,
(SELECT person_score(p.id)) DESC
LIMIT 1;
的person_score
功能是相當昂貴的 - 它搜索的人的過去活動的幾個表。數據庫未滿(測試表中只有幾千行)並且重要列上有索引,但仍然調用評分函數使得人員返回函數速度降低了七倍。如果只減慢真正需要排序的查詢,這不會成爲問題 - 爲同一組織工作的完整名稱很少見。不幸的是,EXPLAIN ANALYSE表明,即使只有一個具有給定姓氏的人,也會調用評分函數。
有什麼辦法,以確保在需要時不會破壞查詢到更多的查詢,最後得到的條件僅評估?如果不是,如何儘可能快地進行拆分(並在它們之間傳遞數據)?
一個可能的解決方案是將查詢等同於名字和組織的等級,將其存儲在數組中(而不是像現在這樣的普通整數),然後僅當數組長度大於1整數時運行評分函數。然而,這感覺很笨拙,我擔心這在常規情況下不會使功能更快(對於名字來說速度較慢)。我也只是一個非常粗略的想法如何去做,我不想在我知道這是必要的之前開始嘗試。
你能把它分解成子選擇嗎?例如(選擇pid FROM person p WHERE p.lastname = _lastname AND(_firstname IS NULL OR inic(p.firstname)= _inic) ORDER BY(p.firstname = _firstname)DESC,(p.organization = _org)DESC)作爲P order by(SELECT person_score(p.id))DESC Limit 1 ----這種方式只對有限的匹配記錄集合運行功能 – Traci 2014-09-25 07:57:51
最明顯的解決方法是將分數預先計算在不同的表中。您必須評估您是否需要實時分數,或者是否可能會過時,如果您可以編制更新查詢以在工作負載較低的時間或任何時候運行......或者,如果您需要實時分數,則可以修改應用程序以在需要時更新分數,或創建觸發器來執行此操作。這看起來像經典的賬戶餘額問題:從不嘗試在運行中計算它,但是預先計算它。 – JotaBe 2014-09-25 08:14:53
@JotaBe:我不需要得分很近,所以你的解決方案看起來很理想。將您的評論擴展爲答案,我會接受它;或者我會明天自己實施這個解決方案並自我回答。 – 2014-09-25 08:56:37