還是之前做那個二級目錄程序(二級目錄租賃之iis反向代理設置方法),程序沒有問題,只是對方要解析到xx目錄,而不能解析到xx/目錄,讓我很疑惑,但沒轍,得聽人家的話,最終把相對路徑改成了絕對路徑。
程序已經上線了,但同時反映速度很慢,有的時候很卡,登錄服務器發現cpu占用趨近100%,主要是mysql導致的。服務器配置應該還算可以(4核8G),所以直接看軟件環境。首選看了一下mysql配置文件,發現tmp_table_size和max_heap_table_size都是32M,于是修改了一下,前者改成200M,后者改成500M,重啟mysql,發現cpu占用只有不到10%了!
以為就這樣就解決問題了,遺憾的是沒有還沒來得及高興,cpu占用又上去了(剛才之所以下來,應該是剛重啟mysql,網站的訪問量不到,計算量不到)。
繼續,登錄mysql,執行show processlist,發現幾條sql語句有很大問題:
select * from gk_temp where uid=44 order by rand() limit 1
這是自動發布(不了解自動發布的可以看這里:虛擬主機網站定時自動發布的思路與實現方法(php)),當有用戶訪問網站的時候從臨時表隨機取一條數據發布寫入到正式表中,每個用戶取一條。rand()本來就不好,而用戶數越多,這樣不好的語句就越多……本案用的是兩張表,而不是如以往一樣放在一張表中,通過特定字段來控制是否發布。之所以這樣做,是因為用戶每個時間段發布的內容都很相似,如果直接按順序發布,那么新發布的內容很相似。所以就用了新表,隨機取。
期初再做的時候沒想到會有這么大的量,就用rand()湊合著用了,無奈只好修改一下,先試試不隨機:
select * from gk_temp where uid=44 order by id desc limit 1
效果很明顯,cpu直接降到了不到5%,但如前面所說,不是我期望的效果啊,還是得隨機,繼續改吧:
SELECT * FROM gk_temp AS u1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `gk_temp`)-(SELECT MIN(id) FROM gk_temp))+(SELECT MIN(id) FROM gk_temp)) AS id) AS u2 WHERE (u1.id >= u2.id and `uid`=44) ORDER BY u1.id LIMIT 1
效果一般,cpu占用在50%左右浮動,后臺操作的時候還是會接近100%,因為后臺發布數據的時候也有類似這樣的sql。還有什么更好的隨機查詢語句呢?
百度了很久,也沒有找到合適的解決方案,看來我的思路得改。
期初的程序是,針對每個用戶隨機取一條,發布。這樣用戶數越多,隨機sql也就越多,效果是不錯的,能保證每個用戶實時都有數據發布,但性能是差勁的,改——不區分用戶,直接隨機所有數據,隨機到誰就是誰了,為了讓隨機更隨機一點(上面的語句隨機出來的是連續的數據),換了一下sql,大概是這樣,每次隨機取n條,不區分用戶來發布:
SELECT * FROM gk_temp WHERE id >= ((SELECT MAX(id) FROM gk_temp)-(SELECT MIN(id) FROM gk_temp)) * RAND() + (SELECT MIN(id) FROM gk_temp) LIMIT 5
沒有后臺操作(同事都下班了,悲催?。?,mysql最高cpu占用10%左右,還行。
看來,魚和熊掌有的時候真的需要取舍,思路也很重要,我們只能在效果與性能之前權衡。只是后臺部分的數據查詢好像沒有辦法更好優化,也沒有其他思路可走了……先就這樣吧,明天再看看有無可能
© 致遠 2021-06-27,原創內容,轉載請注明出錯:mysql導致cpu占用趨近100%