藉口,我熟悉NULL值和空字符串之間的語義差異。NULL或空字符串更有效/自然嗎?
我有一個MySQL表,我用它們的IP地址存儲了很多主機名(作爲字符串),並想知道在主機名無法解析的情況下看起來更自然(或有效的存儲智能)。
NULL值或空字符串(在這種情況下,它可能應該是一個VARCHAR而不是CHAR)
我會傾向於一個NULL值,但我想有這個確認或disconfirmed。
藉口,我熟悉NULL值和空字符串之間的語義差異。NULL或空字符串更有效/自然嗎?
我有一個MySQL表,我用它們的IP地址存儲了很多主機名(作爲字符串),並想知道在主機名無法解析的情況下看起來更自然(或有效的存儲智能)。
NULL值或空字符串(在這種情況下,它可能應該是一個VARCHAR而不是CHAR)
我會傾向於一個NULL值,但我想有這個確認或disconfirmed。
在MyISAM MYSQL每行保存一位不使用NULL。如上所述here:
聲明列NULL可以減少允許的最大列數。對於MyISAM表,NULL列需要額外的空間來記錄它們的值是否爲NULL。每個NULL列需要額外一位,四捨五入到最接近的字節。
看看here還有:
此外,雖然一個NULL本身不需要任何存儲空間,NDBCLUSTER儲備每行4個字節,如果表定義包含定義爲NULL的列,多達32個NULL列。 (如果MySQL簇表與多於32個NULL列定義多達64個NULL列,然後每行8個字節被保留。)
此外這也使得數據庫工作更快在它指出here(從stackoverflow拍攝 - @DavidWinterbottom鏈接,我沒有工作,我加了一個不同的SOURSE)
這是很難爲MySQL優化引用可空coumns查詢,因爲他們製作索引,索引統計信息和價值的比較更復雜。一個可爲空的列使用更多的存儲空間,並且需要MySQL內部的特殊處理。當一個可爲空的列被索引時,它需要每個條目多一個字節,甚至可能導致在MyISAM中將固定大小的內聯(例如單個整數列上的索引)轉換爲可變大小的列。
在大多數情況下,當與COUNT()
和其它聚合函數組合,但你也可以看到根據您的需要一個NULL的行爲非NULL值的行爲更容易預測。
由於它是表示here,不是所有的組(集合)函數忽略NULL例如COUNT()
會給你不同結果COUNT(*)
爲一列包含NULL值。
另一方面,因爲NULL更好地反映了入口的含義 - 它是一個未知的值,如果你想要統計所有的主機,你可能會像它一樣運行。
null行爲對我來說從來都不是問題。你會如此友善地發佈一個關於NULL值位大小的可敬論據的鏈接嗎?另一方面,「這也使數據庫工作更快」可以使用一些進一步的示範。 (更大並不總是意味着更慢) – Sebas 2013-05-05 15:05:19
@Legat我會保存這個位嗎?我認爲它會成爲一些內部標誌集合的一部分,因此它會一直存在並佔用空間,只是在不允許NULL的情況下才進行評估。 – user2352129 2013-05-05 15:10:30
感謝您提及您的來源。我清楚地看到它談到了MYISAM,這意味着innodb引擎被豁免。 – Sebas 2013-05-05 15:15:30
Oracle解決了這個問題,並解釋了兩者相同。
Mysql沒有,我不是判斷它,但個人我不喜歡它,因此儘可能多地使用NULL來「標準化」我的代碼。
另外,從關鍵字的重要性來看,NULL正是你想要的,因爲它意味着db語義中的「未知」。 (糾正我,如果我錯了)
至於語義我同意,這就是爲什麼我寧願傾向於NULL,但我不知道是否空字符串可能有性能或存儲大小(IIRC NULL需要一個額外的標誌)的潛在優勢。 ......至於甲骨文,我並不知道這一點,只在我的研究過程中發現,但我並不真正同意他們。一個空字符串不一定具有與NULL相同的含義,因此不應該被自動轉換 – user2352129 2013-05-05 15:06:30
是的這是正確的關於意義的區別。但是過了一段時間後,你會意識到避免雙重符號更清晰。但這是我想的主觀觀點。 – Sebas 2013-05-05 15:07:39
從性能或存儲的角度來看,您個人不希望優於其他兩種? – user2352129 2013-05-05 15:12:13
我建議你使用NULL
,而NULL的類型是不同於字符串。例如,使用此值過濾掉行或檢測該字段中的值類型等操作會更加輕鬆。
但您也可以輕鬆過濾空字符串。 – user2352129 2013-05-05 15:03:49
首先:考慮密切NULL的不同的語義和空字符串。
二:認識到索引和過濾效果更好,更高效地空字符串比NULL,所以不要使用後者時,你真的是前者。
第三:認識到使用NULL所有表達式易受三值邏輯的非直觀性,除非將NULL宗教聚結以空字符串(或一些其他內容相關有效值)第一。特別地,排除中間定律不再適用,因此,只要評估需要評估術語,表達式A或〜A就不再是同義語。忘記這可能導致非常微妙和難以定位的錯誤。
的未等於運營商這個經常暴露:
When A has the value NULL:
The expression A = 0 returns false;
The expression A <> 0 returns false; and
The expression A OR NOT A returns false!
更新:
我想我的觀點的實質是,他們是不一樣的生物,而是非常不同的東西。每個都有它的位置。第二個地址字段應始終爲非空值(除非您打算允許輸入部分地址或不完整地址),並且它的默認值應始終爲空字符串的有效值和已知值。 NULL應該限於後面將提供有效的和已知的值的情況,事實上o表示某種必須解決的驗證失敗。
從下面OP:
一行將不會被更新。插入時有IP 地址,或者沒有地址(因爲無法解析)。
響應:
那麼我建議使用空字符串爲默認值,並進行現場NON-NULL。必須時只使用NULL,因爲它有微妙的缺點。
我把你弄到最後一段。在我的情況下,人們可能會爭論這兩種解決方案(NULL,主機無法解析,並且是未知的 - 「」,主機無法解析,但嘗試過,因此結果爲空)。 ........從你的迴應中,我並沒有完全明白你會選擇哪種解決方案,你能否詳細說明這一點? – user2352129 2013-05-05 15:50:22
@ user2352129:我猜我的觀點的本質是他們**不是**,而是非常不同的野獸。每個都有它的位置。第二個地址字段應始終爲非空值(除非_intend_允許輸入部分地址或不完整地址),並且它的默認值應始終爲** Empty-String **的_valid和known_值。 ** NULL **應限制在稍後將提供_valid和known_值的情況,實際上o表示必須解決的某種驗證失敗。 ... – 2013-05-05 15:54:33
@ user2352129:在你的例子中,我看不到你已經定義了這個字段的語義,足以作出決定。我懷疑你應該使該字段可以爲空,但將其默認值定義爲** Empty-Sting **。這樣,應用程序可以明確地指定** NULL **來表示「它存在,但我需要去查找值」;但是在創建初始記錄時,默認的** Empty-String **意思是「沒有一個」。這是表格行的正確語義嗎? – 2013-05-05 15:55:25
這是一種主觀的,但NULL帶有「不適用」的意思,這似乎是最自然的。效率不應該是一個因素。 – 2013-05-05 15:05:08
@傑克那麼,效率總是一個因素;) – user2352129 2013-05-05 15:11:19
主機名是否必須是唯一的?你有沒有想過多個IP地址解析爲相同的主機名? – 2013-05-05 15:16:30