前往
大廳
主題

優化程式碼讚

夜貓Nightcats | 2024-04-30 23:22:20 | 巴幣 4 | 人氣 60

要把一張資料表輸出成excel
本來是參考其他相同功能的程式碼
先從資料庫撈出需要輸出的資料之後用迴圈跑一遍
把所有值轉換一下 比如1跟0轉成是和否、下拉選單是存int所以要重新轉成選項名字這樣
還有一些欄位需要合併顯示的也要處理 不過這都不是重點

重點是我們存資料是用doctrine orm去管理
簡單說就是把資料表變成一個個class
一張表就是一個class 一筆資料就是一個這個class的物件
要存取資料的某個欄位的時候直接get物件屬性就好了
像是people->getName()這樣
然後有時候有些表會需要跟其他表作關聯
比如有個表family 裡面可以塞任意數量的people
在資料庫中的形式是 people表會有一個欄位用來儲存family的id
這樣就可以知道這個people是哪個family的
而在doctrine中 則是family有個people陣列 需要拿到people的時候只要family->getPeople()就好了
相對的也可以people->getFamily() 算是滿方便的了

不過需要注意的地方來了
雖然看上去你可以直接呼叫family->getPeople()拿到people,感覺就像是這些people已經存在family物件裡面一樣
但實際上這些people根本不在family裡面,而是在執行getPeople()的時候doctrine在背後幫你用sql從資料庫裡撈出來的
等於說每次存取關聯表在背景都需要跑一次sql
如果有100個family 迴圈跑下來就是100次
而我需要輸出的那張表? 他有4個關聯表! 其中一個表還又去關聯別的表.. 瘋狂套娃

光是測試機的20多筆假資料就可以跑出100多次sql了
如果到了正式機估計直接就得上好幾千 雖然跑是能跑但效能一定不好看

後來我的解決方式是 在迴圈外先把所有需要的資料一次全拿到 而不是在迴圈內一筆一筆撈
同時合併對同一張表的sql 比如都是查people 這筆查id=1那筆查id=2 其實可以改成 id IN(1,2)
迴圈內在根據需要去過濾就好了

改好了後sql次數從100次多變到只剩下12次 而且就算新增資料也不會增加
本來新增資料最少得多4次 最多可能沒上限 看他表又關聯表的那個欄位填了幾個
以測試機來看 少100次sql速度快了10倍 到了正式機只會差更多

現在只需要擔心一次把所有資料存起來會不會讓伺服器記憶體爆掉就好了XD
不過那也得等上正式機再說了
诶嘿~

創作回應

悠露
https://media.tenor.com/WHOwHxdVSQIAAAAC/capoo-capoo-type.gif
2024-05-01 06:57:05

更多創作