一些MySQL使用時(shí)遵循的規(guī)范(初版)

首發(fā)于fxm5547的博客

建表

  • 見名知意贩毕,表名和字段名以下劃線分割

  • 注意單復(fù)數(shù),如用戶表為users仆嗦,而不是user

  • 詳細(xì)定義表辉阶、字段和索引的備注

  • 編碼統(tǒng)一為utf8mb4,不需要存儲(chǔ)emoji表情等特殊字符的字段編碼可單獨(dú)改為utf8(varchar utf8建索引的最大長度為255,varchar utf8mb4建索引的最大長度為191)谆甜,數(shù)據(jù)鏈接編碼使用utf8mb4

  • 字段類型嚴(yán)格定義垃僚,需要注意類型、長度规辱、是否為空谆棺、無符號(hào)(確定不會(huì)存儲(chǔ)復(fù)數(shù)的字段加UNSIGNED)等

  • 主鍵一般用bigint、自增罕袋,關(guān)聯(lián)表 / 無實(shí)際意義表的主鍵命名為rec_id改淑,其他表的主鍵要見名知意,如goods_id

  • 字段(單字段或多字段)數(shù)據(jù)不能重復(fù)時(shí)浴讯,一定要定義Unique索引

  • 每張表一定要包含兩個(gè)字段created_at(記錄生成時(shí)間)和updated_at(記錄最近修改時(shí)間)朵夏;通過數(shù)據(jù)庫的timestamp字段類型實(shí)現(xiàn),無須代碼控制榆纽,http://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html
    ALTER TABLE test ADD COLUMN created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP , ADD COLUMN updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

    圖片

  • 基于性能的考慮仰猖,所有字段均不能為空,即全部NOT NULL奈籽,設(shè)置默認(rèn)值

  • 存儲(chǔ)開關(guān)饥侵、選項(xiàng)數(shù)據(jù)的字段,通常使用tinyint(1)非UNSIGNED類型衣屏,通常1為打開爆捞;0為關(guān)閉,多類型時(shí)勾拉,從1開始定義

SQL / PHQL

  • 程序中,SQL的關(guān)鍵字一定要大寫

  • 新增SQL時(shí)一定要驗(yàn)證其性能盗温,添加必要的索引藕赞,使用EXPLAIN/DESC關(guān)鍵字驗(yàn)證索引是否命中

  • 數(shù)據(jù)庫SQL語句中,所有數(shù)據(jù)必須加單引號(hào)卖局,無論數(shù)值還是字串斧蜕,以避免可能的注入漏洞和SQL錯(cuò)誤

  • 盡可能使用數(shù)據(jù)綁定的方式進(jìn)行數(shù)據(jù)查詢

  • 多表操作時(shí),對表進(jìn)行定義別名砚偶,定義別名的規(guī)則:取表中每個(gè)單詞的首字母作為別名批销,如ecs_ayb_content_categories AS acc

  • 只查需要的列,即使表的字段很少

讀寫分離

  • 訪問數(shù)據(jù)庫方式讀寫分開染坯。db為寫均芽,rDb為讀。

  • 使用PHQL和表ORM方式會(huì)自動(dòng)識(shí)別讀寫數(shù)據(jù)庫

  • 需要注意情況如下:

SELECT語句使用rDb单鹿。rDb不能執(zhí)行更新掀宋、新增、刪除操作。
$app->rDb->query("SELECT * FROM ecs_user_baby WHERE baby_id=2 LIMIT 1")
$app->db->query("UPDATE ecs_user_baby SET read_count=read_count WHERE baby_id=2 LIMIT 1");

在Model中讀數(shù)據(jù)庫也可以使用getReadConnection方法劲妙,寫使用getWriteConnection方法湃鹊。
$userGoodsShelf = new UserGoodsShelf();
$userGoodsShelf->getReadConnection()->execute("SELECT * FROM ecs_user_baby LIMIT 1 ");

索引相關(guān)

參考:

基本準(zhǔn)則

  • 程序開發(fā)時(shí),時(shí)刻注意新寫的SQL是否需要增加索引或優(yōu)化已有索引(聯(lián)合索引或單索引)镣奋,以explain/desc驗(yàn)證索引是否命中

  • 建立Unique索引币呵,使用INSERT INTO ... ON DUPLICATE KEY UPDATE ...完成一些需要兩條SQL完成的復(fù)雜邏輯;禁止使用REPLACE ... INTO ...侨颈,它會(huì)帶來一些問題

  • 定期查看慢查詢?nèi)沼浻嘤瑑?yōu)化慢SQL,目前閥值時(shí)1s


    圖片

B+樹索引

1肛搬、最左前綴匹配原則没佑,非常重要的原則,mysql會(huì)一直向右匹配直到遇到范圍查詢(>温赔、<蛤奢、between、like)就停止匹配陶贼,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引啤贩,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到拜秧,a,b,d的順序可以任意調(diào)整痹屹。

2、=和in可以亂序枉氮,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序志衍,mysql的查詢優(yōu)化器會(huì)幫你優(yōu)化成索引可以識(shí)別的形式

3、盡量選擇區(qū)分度高的列作為索引,區(qū)分度的公式是count(distinct col)/count(*)聊替,表示字段不重復(fù)的比例楼肪,比例越大我們掃描的記錄數(shù)越少,唯一鍵的區(qū)分度是1惹悄,而一些狀態(tài)春叫、性別字段可能在大數(shù)據(jù)面前區(qū)分度就是0,那可能有人會(huì)問泣港,這個(gè)比例有什么經(jīng)驗(yàn)值嗎暂殖?使用場景不同,這個(gè)值也很難確定当纱,一般需要join的字段我們都要求是0.1以上呛每,即平均1條掃描10條記錄

4、索引列不能參與計(jì)算坡氯,保持列“干凈”莉给,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引毙石,原因很簡單,b+樹中存的都是數(shù)據(jù)表中的字段值颓遏,但進(jìn)行檢索時(shí)徐矩,需要把所有元素都應(yīng)用函數(shù)才能比較,顯然成本太大叁幢。所以語句應(yīng)該寫成create_time = unix_timestamp(’2014-05-29’);

5滤灯、盡量的擴(kuò)展索引,不要新建索引曼玩。比如表中已經(jīng)有a的索引鳞骤,現(xiàn)在要加(a,b)的索引,那么只需要修改原來的索引即可

慢查詢優(yōu)化基本步驟

0黍判、先運(yùn)行看看是否真的很慢豫尽,注意設(shè)置SQL_NO_CACHE

1、where條件單表查顷帖,鎖定最小返回記錄表美旧。這句話的意思是把查詢語句的where都應(yīng)用到表中返回的記錄數(shù)最小的表開始查起,單表每個(gè)字段分別查詢贬墩,看哪個(gè)字段的區(qū)分度最高

2榴嗅、explain查看執(zhí)行計(jì)劃,是否與1預(yù)期一致(從鎖定記錄較少的表開始查詢)

3陶舞、order by limit 形式的sql語句讓排序的表優(yōu)先查

全文索引

MySQL 5.6.4版本起InnoDB已經(jīng)支持全文索引嗽测,簡單實(shí)例:

  • 新建索引:
    alter table articles add fulltext index(title,body);

  • 搜索 title 和 body 包含 database和MySQL關(guān)鍵字的記錄:
    SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database,MySQL');

  • 搜索title和body中包含 MySQL ,但是不能有 YourSQL 的結(jié)果:
    SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

是否使用數(shù)據(jù)庫全文索引視情況而定肿孵,數(shù)據(jù)量大應(yīng)該使用Elasticsearch

其他

  • 默認(rèn)圖片應(yīng)該在程序邏輯中加唠粥,不應(yīng)該存入數(shù)據(jù)庫
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市停做,隨后出現(xiàn)的幾起案子厅贪,更是在濱河造成了極大的恐慌,老刑警劉巖雅宾,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異葵硕,居然都是意外死亡眉抬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門懈凹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜀变,“玉大人,你說我怎么就攤上這事介评】獗保” “怎么了爬舰?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寒瓦。 經(jīng)常有香客問我情屹,道長,這世上最難降的妖魔是什么杂腰? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任垃你,我火速辦了婚禮,結(jié)果婚禮上喂很,老公的妹妹穿的比我還像新娘惜颇。我一直安慰自己,他們只是感情好少辣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布凌摄。 她就那樣靜靜地躺著,像睡著了一般漓帅。 火紅的嫁衣襯著肌膚如雪锨亏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天煎殷,我揣著相機(jī)與錄音屯伞,去河邊找鬼。 笑死豪直,一個(gè)胖子當(dāng)著我的面吹牛劣摇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弓乙,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼末融,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暇韧?” 一聲冷哼從身側(cè)響起勾习,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懈玻,沒想到半個(gè)月后巧婶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涂乌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年艺栈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾盒。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡湿右,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罚勾,到底是詐尸還是另有隱情毅人,我是刑警寧澤吭狡,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站丈莺,受9級(jí)特大地震影響划煮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜场刑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一般此、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧牵现,春花似錦铐懊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贼急,卻和暖如春茅茂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背太抓。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工空闲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人走敌。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓碴倾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親掉丽。 傳聞我的和親對象是個(gè)殘疾皇子跌榔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351