iT邦幫忙

1

mysql 單一欄位儲存多資料 資源用量

  • 分享至 

  • xImage

各位大大好
小弟好奇一個問題
由於網上打的關鍵字查到的都不是想要的
所以上來詢問各位大大
我的問題是:
若今天有一種資料 是同性質但是可複選
像 喜歡什麼水果(假設固定5種水果裡面挑)
前端的呈現就是複選checkbox的樣式
而且並不會運用這些值來搜尋
那我DB用一個欄位
去存這些複選資料比較好
Table就會像這樣

name        fruit
Alex  apple,banana,orange
Oni   banana,grape,orange
Ruff  apple,strawberry

還是開5個欄位
Table就會長這樣

name   apple  banana grape strawberry orange
Alex     1      1      0       0        1
Oni      0      1      1       0        1
Ruff     1      0      0       1        0

目前一個指導我的前輩所寫的方式都是第二種
所以資料表都超多欄位

雖然兩種效果一樣
但我總覺得對資源的影響是有差別的
我直覺是第一種會比較好

請各位大大指點一下小弟

看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2020-02-07 16:05:19 檢舉
ㄜ...就正規化而言是第二種。
第一種我只會用在欄位不固定的時候去做。
slime iT邦大師 1 級 ‧ 2020-02-07 16:08:48 檢舉
我也不排斥這種:
Alex, 1, Apple;
Alex, 2, Banana;
Alex, 3, Orange;
Oni, 1, Banana;
....
st474ddr iT邦新手 2 級 ‧ 2020-02-07 16:16:50 檢舉
@froce
原來是這樣

@slime
不好意思 我沒講清楚
因為只有一個欄位是複選
這樣會有一堆其他的欄位重複
Season iT邦研究生 3 級 ‧ 2020-02-07 16:41:00 檢舉
不曉得是否跟slime大大說的差不多
我是會建個水果table 跟 2個互相對應的table
alex 喜歡apple(id=1), banana(id=2), orange(id=3)...
互相對應的table 紀錄alex ID 與 水果ID
slime iT邦大師 1 級 ‧ 2020-02-07 16:44:57 檢舉
思考一下:
方法1: 查詢後要再利用逗點分割, 才能處理, 所以儲存空間"可能"較省, 而程式負擔較大.
方法2: 查詢時單一問題的答案要定義, 程式較簡單, 不過資料庫無論是否有資料, 該欄都需要占有空間存"空白".
方法3: 有選擇存入才會占有空間, 程式需要思考一下定義, 不過不用再去拆逗號, 應該比方法1省一些資源, 而且如果題目定義好, 可以再省一點:
Alex, 1
Alex, 2
Alex, 5
Oni, 2
Oni, 3
Oni, 5
未填的再補比對為 NULL
slime iT邦大師 1 級 ‧ 2020-02-07 16:47:58 檢舉
方法4:
Alex, 25;
Oni, 13;
(猜猜看怎樣存的 ^^ )

因為這些都是例子而已, 可能寫幾個基本查詢, 然後產生個 10 萬筆看看, 再模擬查詢/修改動作, 測試一下使用的時間跟資料庫空間去規劃.

(註: 方法4是用2進位: 16,8,4,2,1 去加總.)
froce iT邦大師 1 級 ‧ 2020-02-07 16:53:19 檢舉
其實slime的才是正解
甚至可以再拆一張表,存選項和數值的對應,然後紀錄數值就好了。

最近都在忙別的事,沒寫程式果然有差,哈
小魚 iT邦大師 1 級 ‧ 2020-02-08 07:46:29 檢舉
話說回來,
1, 2, 4 這種只能用在數量比較少的吧,
如果來的1000個會如何?
slime iT邦大師 1 級 ‧ 2020-02-08 17:04:03 檢舉
其實我原本的構想比較接近 阿展展展 的回答: "先跳脫只有兩種做法的思考".

然後再把資料庫用的資源跟程式(演算法)的可能測試方向提一下, 讓發問者找到適合這個案子的做法, 才是他能學到的.
st474ddr iT邦新手 2 級 ‧ 2020-02-09 16:02:16 檢舉
@slime
感謝大大
因為主要架構不只這個欄位而已
我原本的意思是想說 會不會插入太多只有部分欄位值相異 但其他值都相同的情況
就像是
Alex, 1, Apple,hiking,cancer,A,8/15;
Alex, 2, Banana,hiking,cancer,A,8/15;
Alex, 3, Orange,hiking,cancer,A,8/15;
所以才會有這個問題的產生
不過看了這麼多大大熱心的回答
心中的答案大概也有十之八九了
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1

其實我用的方式也是 slime 用的方式

最單純的對應法。
效能方面也不太需要擔心。索引下好就行了

後期擴展也比較好。

st474ddr iT邦新手 2 級 ‧ 2020-02-10 09:27:30 檢舉

了解
感謝大大

2
ckp6250
iT邦好手 1 級 ‧ 2020-02-07 20:01:18

我以前都把重心放在【儲存空間大小】、【電腦效能】上,
後來發現,空間越來越便宜,電腦越來越快,
我現在都把重心放在【程式最好寫】上頭啦。

雖然,0.01秒和0.02秒,表面上效能差了一倍,
但,對於使用者的感受來說,是一樣的。

st474ddr iT邦新手 2 級 ‧ 2020-02-09 14:34:16 檢舉

前輩也是這樣說的
都說DB不用錢

1
阿展展展
iT邦好手 1 級 ‧ 2020-02-07 23:03:06

你的DB怎麼設計是來自於需求是什麼 以及擴展性是什麼 以及 之後可能會有什麼變更
你所提供的命題其實是很難回答的
因為 你只說出了你的想法 以及前輩教你的做法
而 之後你會如何存取這個DB 這個欄位 要做什麼操作
你多常會需要寫一次這些欄位 才是考量的要點

對於效能的部分 在幾千 幾萬筆資料來說 現在的硬體跑起來不會差到很多
但是到 幾十萬 幾百萬 甚至上千萬筆的時候 就會變得很明顯
甚至於...卡死

用一攔一欄的 true/false 值來存 或者用 {"A":1,"B":0,"C":1,...} 來存
各有各的優點,當然也有其缺點
所以你問 這樣比較好 還是那樣比較好 其實是不太容易有答案的

以上淺見

st474ddr iT邦新手 2 級 ‧ 2020-02-09 14:35:26 檢舉

對 其實我也有想過問題是不是沒辦法描述的太具體
不過這個疑竇在心中也有段時間了
還是想問問各位大大們的想法

0
rogeryao
iT邦超人 7 級 ‧ 2020-02-09 00:54:39

"而且並不會運用這些值來搜尋" <== 這是個很奇怪的狀況
基本上,寫到資料庫的 data 都有可能用任何查詢條件來查詢(單一水果統計依月份,去年同比,....同類水果統計,...累計...)

若以查詢的角度而言 :
1.方法一 : 單一欄位儲存多資料 => 查詢 banana 時 , fruit 欄位內的字串都要額外拆解運算 ,當資料大時,時間都耗在拆解字串(甚至串聯到其他 table 做其他運算..更耗時) ,可運作但是很可能會 Timeout ,無資料回傳
2.方法二 : 資料的儲存僅限於 "apple,banana,grape,strawberry,orange"這幾個欄位,若有新增
fruit 是 Cherry 時 , 不只要新增欄位還要改 code ; 若水果本身又要分類去統計 ,....那...如何做 ?

建議作法 :
A.資料歸資料:基本上要符合正規化
B.報表歸報表:符合正規化的 table 基本上都有方法行轉列,或是列轉行
table 應該會類似 :

fruit   Employee    Qty
apple       Alex      1
banana      Alex      1
grape       Alex      0
st474ddr iT邦新手 2 級 ‧ 2020-02-09 15:56:39 檢舉

而且並不會運用這些值來搜尋" <== 這是個很奇怪的狀況

由於這個欄位的資料並不是說最重要的 只是附加的紀錄
可能目前我在做的是 個人資料的建檔
主要的搜尋條件就會變得比較像是 姓名 身分證 出生日...
因為若是要拿這些值來搜尋
我的第一種方法就不太可行了
也就是大大您講的第一種情況

不過看了這麼多大大幫我解惑 我心裡也有個底了

我要發表回答

立即登入回答