簡體   English   中英

SQL查詢中年齡計算的性能

[英]Performance of age calculation in SQL query

我正在構建一個動態MySQL用戶搜索查詢,該查詢將能夠處理許多不同的搜索條件。 我考慮編寫存儲過程,但最終在客戶端(PHP中的預備語句)中構建了查詢。 這些標准之一是能夠搜索用戶的年齡,即X和Y歲之間。 我想知道如何盡可能有效地做到這一點。 結束查詢將非常復雜,並且具有多個聯接,並且將來可能在數百萬行上運行,因此我需要在可能的地方對其進行優化。 我將用戶的出生日期存儲在具有YYYY-MM-DD格式的索引DATE列中。 我具有以下用於計算用戶年齡的用戶定義函數(UDF):

RETURN (DATE_FORMAT(current_time, '%Y') - DATE_FORMAT(date_of_birth, '%Y') - (DATE_FORMAT(current_time, '00-%m-%d') < DATE_FORMAT(date_of_birth, '00-%m-%d')));

計算的細節並不重要。 我更關心它的用法。 我的擔心之一是,在WHERE子句中使用此UDF會顯着降低查詢速度,因為即使我使UDF具有確定性,它也需要在每一行上運行。 我不能保證在檢查年齡之前,還有其他條件可以縮小匹配行的范圍。 我不能只將出生日期與日期核對一下,因為那是不准確的。 我在考慮是否將上述計算從UDF中取出並直接將其嵌入查詢的WHERE子句中會產生顯着差異(我認為是)。 不利的一面是,WHERE子句會因這種計算而變得更加復雜(或者實際上是兩個,除非有一種方法可以重用結果)。 但是我想沒有辦法避免這些計算。 是否在WHERE子句中執行此計算是改善性能的方法,還是有更好的方法?

從理論上講,我想我什至可以在user表中添加age列,並計算用戶每晚注冊並運行計划的工作/臨時工作時的年齡,以更新生日為今天的用戶的年齡(如果可以有效地選擇該年齡的話) )。 這肯定會加快我的搜索查詢速度,但是會引入冗余數據。 因此,我真的只想在搜索查詢本身無法有效完成計算的情況下執行此操作。

因此,總結一下:我需要搜索年齡在一定范圍內(例如25到30歲)的用戶。 我應該在WHERE子句中計算年齡,還是因為必須在每一行上執行而很慢? 是我必須做出的犧牲,還是我有更好的選擇?

任何幫助深表感謝。

如果要基於當前日期進行准確的年齡計算,則應嘗試以下操作:

where date_of_birth between date(now()) - interval 30 years and date(now()) - interval 25 year

在這種情況下,您不會date_of_birth進行任何轉換,因此可以將索引用於查詢。

另外,您不應使用類似以下的表達式:

DATE_FORMAT(current_time, '%Y') - DATE_FORMAT(date_of_birth, '%Y')

DATE_FORMAT()將參數轉換為字符串。 您需要一個數字,因此只需使用:

year(now()) - year(date_of_birth)

它將從日期到字符串的轉換保存為int,而直接將其直接轉換為int。

編輯:

要處理“ 25”的實際含義是“最多26”,請使用顯式比較來實現邏輯:

where date_of_birth >= date(now()) - interval 30 years and
      date_of_birth < date(now()) - interval 26 year

這實際上與UDF或存儲過程的性能無關。 每當您在列周圍使用函數時,MySQL均無法在其上使用索引。

如果您不希望Highlander出現在數據庫中,則年齡的tinyint無符號列就足夠了(0-255)。 每行花費1個字節。 您可以在上面放一個索引。 此列添加到表的開銷微不足道。 不要擔心存儲空間。 另一方面,存儲性能是更大的關注點。 完全掃描搜索的費用遠遠超過此1字節的額外列。

您可以使用date_of_birth列上的觸發器來更新此列。 當然,如果您在表上放置適當的索引,則夜間cronjob可以有效地選擇date_of_birth = DATE(NOW())的行並將年齡增加一。 (我將使用存儲過程來執行此操作,以便可以在MySQL中完成所有操作)。

ps .:您編寫的函數似乎是存儲函數,而不是UDF。 存儲的函數用SQL編寫並存儲在MySQL中。 UDF用C編寫,編譯為.so或.dll文件,然后加載到MySQL。 有關更多信息,您可以檢查: SP和UDF的幫助?

暫無
暫無

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

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