數據庫-你可能忽略的東西

數據庫的使用你可能忽略了這些

https://www.cnblogs.com/joylee/p/7768457.html

數據庫的管理是一個很是專業的事情,對數據庫的調優、監控通常是由數據庫工程師完成,可是開發人員也常常與數據庫打交道,即便是簡單的增刪改查也是有不少竅門,這裏,一塊兒來聊聊數據庫中很容易忽略的問題。html

字段長度省着點用 先說說咱們經常使用的類型的存儲長度:java

列類型 存儲長度 tinyint 1字節 smallint 2字節 int 4字節 bigint 8字節 float 4字節 decimal(m,d) 0-4字節 datetime 8字節 timestamp 4字節 char(m) m個字節 varchar(m) 可變長度 text 可變長度 很明顯,不一樣的類型存儲的長度有很大區別的,對查詢的效率有影響,字段長度對索引的影響是很大的。node

字符串字段長度都差很少的,能夠預估長度的,用char 字符串長度差別大,用varchar,限制長度,不要浪費空間 整型根據大小,選擇合適的類型 時間建議用timestamp 建議使用decimal,不建議使用float,若是是價格,能夠考慮用int或bigint,如1元,存儲的就是100 放棄uuid(guid)的使用 無論是uuid,仍是guid,使用的時候都是爲了不同時生成重複的ID,可是建議考慮其餘方案,緣由以下:mysql

uuid沒有順序 uuid太長 uuid規則徹底不可控 推薦的方案用bigint(首選),或者char來存儲,生成方式參考snowflake的算法,有順序、長度固定、比uuid更短,固然,也幾乎不會重複。linux

大表減小聯表,最好是單表查詢 單表查詢的優點不少,查詢效率極高,便於分表分庫擴展,可是不少時候你們都以爲真正實現起來不太現實,徹底失去了關係數據庫的意義,可是單表的性能優點太明顯,通常總會有辦法解決的:程序員

合理的冗餘字段 配合內存數據庫(redis\mongodb)使用 聯表變屢次查詢(下文會有說明) 若是考慮都後期數據量大,須要分表分庫,就應該儘早實時單表查詢,如今的數據庫分表分庫的中間件基本都沒法支持聯表查詢。即便如mycat最多支持兩個表的聯表查詢,可是也有很明顯的性能損耗。redis

索引的正確處理方式 索引的優點這裏就很少說了,索引使用不當會有反效果:算法

數據量很小的表,不須要索引 一個表的索引不宜過多,建議最多就5個,索引不可能知足全部的場景,可是了個知足絕大部分的場景 mysql 和 sqlserver的索引差異還挺大的,須要注意。例如: mysql索引字段的順序對性能有很大影響,sqlserver優化過,影響很小 多查幾回比聯表可能要好 提出這個方案相信會獲得不少人的反對,可是我相信這個結論仍是很是適合數據量大的場景。多查幾回數據庫有這麼幾個弊端:sql

增長了網絡消耗 增長了數據庫的鏈接數 其實,這兩個問題在如今基本均可以忽略的,數據庫和應用的鏈接基本都是內網,這個網絡鏈接的效率仍是很高的。數據庫對鏈接池的優化已經比較成熟了,鏈接數只要不是太多,影響也不會太嚴重,可是多查幾回的優點卻不少:mongodb

單表效率更高 便於後期擴展分表分庫庫 有效利用數據庫自己的結果緩存 減小鎖表,聯表會鎖多個表 固然,多查幾回這個度必定要把握。千萬不要在一個循環裏面查詢數據庫。咱們也應該儘可能減小查詢數據庫的次數。咱們能夠接受1次查詢變2次查詢,若是你變成10次查詢,那就要放棄了。 舉個例子: 查詢商品的時候,須要顯示分類表的分類名

select category.name,product.name from product inner join category on p.categoryid=category.id 建議的方式:

select categoryid,name from product select categoryname from category where categoryid in ('','','','') 固然,你能夠再優化一下,查詢分類名以前,對product的categoryid排序一下,這樣速度更快。由於咱們前面已經用snowflake生成了有順序的主鍵了。 補充一下,in的效率並非你想象的那麼慢,若是保持在100個節點(不少書籍介紹1000個節點,咱們保守一點),性能仍是很高的。

儘可能使用簡單的數據庫腳本 不少用過 .net Entity Framework 的人都說這個框架太慢,其實慢主要是兩點:錯誤的使用延遲加載(外鍵關聯)、生成SQL編譯太慢。Entity Framework生成的SQL腳本有太多沒用的東西,致使編譯太慢。 數據庫腳本儘可能使用簡單的,不要用太長的一個SQL腳本,會致使初次執行的時候,編譯SQL腳本花費太多的時間。

儘可能去避免聚合操做 聚合操做如count,group等,是數據庫性能的大殺手,常常會出現大面積的表掃描和索表的狀況,因此你們能看到不少平臺都把數量的計算給隱藏了,商品查詢不去實時顯示count的結果。如淘寶,就不顯示查詢結果的數量,只是顯示前100頁。 避免聚合操做的方法就是將實時的count計算結果用字段去存儲,去累加這個結果。固然,也能夠考慮用spark等實時計算框架去處理,這種高深的技術,不在這次討論範圍內。(PS:主要是我也不懂)

總結 程序的優化不少時候都是一些細節的問題,更應該注意平時的積累,阿里SQL的規範有不少能夠吸收的地方,以上也是本身工做中的一些總結,歡迎你們補充。

https://www.cnblogs.com/joylee/p/9521741.html

前言 以前寫過一篇文章《數據庫的使用你可能忽略了這些》,主要是從一些你們使用使用時容易忽略的地方,如:字段長度、表設計等來講明,這篇文章一樣也是這樣的主題,只是從另外的幾個方面來講說數據庫使用中,容易忽略,致使入坑的地方。

合理預估數據量 在數據庫進行表設計的時候,就應該評估可能產生的數據量,數據量會對整個開發和代碼的健壯性有很大的影響。開發一個數據量萬級別、十萬級別、百萬級別、千萬以上級別數量的應用,在開發思路、技術選型、架構都能都要很大的差異。 基本上的個人原則是:

萬級別的數據庫,能夠隨意一點,SQL編寫有好的習慣; 十萬級別,注意索引,注意聯表性能; 百萬級別,儘可能減小聯表,儘可能不要作彙總查詢,如查總數 ; 千萬以上級別,除緩存以外,使用分表分庫 ; 不少系統由於在設計表的時候,沒有很好的預估的後期系統的發展,致使上線不久就出現沒法支撐的狀況,代碼上太多的聯表查詢,不在意基礎的SQL性能,致使數據庫的瓶頸很快就顯現出來,不得不重構系統。設計數據庫的時候,必定是基於業務進行設計的,對業務的發展有必定的預估,看得長遠一點。

合理預估併發訪問量 數據庫有自然的瓶頸,就是併發量。咱們通常會經過緩存來減小數據庫的併發鏈接,以及對數據庫的操做,數據庫的併發,不是隻有大型平臺纔會遇到,不少中小平臺其實也會面臨這樣的問題,例如:

循環進行數據庫的操做 這個問題,上一篇文章我也提到過,不要在循環裏進行數據庫的操做,這個會直接致使數據庫鏈接數暴增,影響很是嚴重。雖然是個比較低級的問題,可是出現的機率實際上是很是高的,在我身邊看到不少不少這種案例了,這種問題,就是須要程序員本身自己避免這些問題,固然,也能夠經過一些手段去監控,找到這些問題,只是會比較麻煩一點。

業務自己的高頻次數據請求 其實有些業務,即便是中小型的平臺,也會有高併發請求數據庫的狀況,常見的例子如:日誌。例如,咱們須要抓取到全部人的操做日誌,或者全部模塊的加載時間,而且持久化保存。若是,當初選型經過Mysql去記錄這些數據,那麼就很容易遇到高併發的問題。這種就是屬於選型的錯誤了。

數據庫對高併發的處理一直是短板,因此應該儘可能避免高併發的數據庫操做,查詢經過緩存處理,增刪改這能夠經過MQ或者Kafka這樣的工具異步進行處理,若是對數據庫的結構化要求不高,則能夠用hbase或者hive進行數據庫的保存。

數據庫線程池的合理使用 如今數據庫的操做都是使用線程池的,線程池主要是用來控制數據庫的鏈接數,其實鏈接池是不屬於數據庫範疇,可是,通常咱們使用和數據庫結合很是緊密,因此在這裏一併說明。 通常線程池都會有這樣的幾個參數:

參數 說明 最小鏈接數 無論是否有數據庫的操做,這幾個鏈接都會一直存在, 最大鏈接數 容許的最大的鏈接數,若是超過了這個數據,則沒法申請鏈接,只能等待,或者異常 回收時間 多長時間會對全部的鏈接進行一次斷開,而後從新鏈接。 釋放時間 多長時間沒有進行操做的鏈接,會釋放 基本全部的鏈接池都會有這幾個參數,可能不一樣的鏈接池參數名不一樣,可是做用是同樣的。 這裏咱們重點說一下最大鏈接數,這個是很容易忽略的一個設置。 不少人設置最大鏈接數的時候,喜歡設置的很大,例如設置爲5000,可是通常mysql的數據庫一個實例鏈接默認才1000,鏈接數超過這個了數據庫也沒法處理,設置的再大實際上是沒用的。

服務器數量 * 最大鏈接數 < 數據庫最大鏈接數

並且,這仍是在一個實例,一個數據庫的狀況下,至於多個數據庫: 我建議

服務器數量 * 最大鏈接數 * 數據庫數量 < 數據庫最大鏈接數

若是單個數據庫佔用了太多的數據庫鏈接,會影響到其餘數據庫,致使其餘數據庫也沒法使用。 固然,這個值你們能夠根據業務去進行合理的估算,高頻的業務分配多一點,低頻的業務分配少一點。不要盲目的一味設置鏈接池的最大值。

總結 現在,雖然各類各樣的存儲方式出現,可是關係數據庫一直是咱們系統的最重要的組成部分,儘可能不要過早暴露數據庫應對併發的短板,設計數據庫和操做數據庫在咱們的開發中應該是一件很神聖的事情,認證對待關係的數據庫的每個操做纔是明智之舉。

擴展閱讀: 數據庫的使用你可能忽略了這些 學會數據庫讀寫分離、分表分庫——用Mycat,這一篇就夠了!

數據庫讀寫分離、分表分庫

https://www.cnblogs.com/joylee/p/7513038.html

系統開發中,數據庫是很是重要的一個點。除了程序的自己的優化,如:SQL語句優化、代碼優化,數據庫的處理自己優化也是很是重要的。主從、熱備、分表分庫等都是系統發展早晚會遇到的技術問題問題。Mycat是一個廣受好評的數據庫中間件,已經在不少產品上進行使用了。但願經過這篇文章的介紹,能學會Mycat的使用。 安裝 Mycat官網:http://www.mycat.io/ 能夠了解下Mycat的背景和應用狀況,這樣使用起來比較有信心。

Mycat下載地址:http://dl.mycat.io/ 官網有個文檔,屬於詳細的介紹,初次入門,看起來比較花時間。

下載: 建議你們選擇 1.6-RELEASE 版本,畢竟是比較穩定的版本。

安裝: 根據不一樣的系統選擇不一樣的版本。包括linux、windows、mac,做者考慮仍是很是周全的,固然,也有源碼版的。(ps:源碼版的下載後,只要配置正確,就能夠正常運行調試,這個贊一下。)

Mycat的安裝其實只要解壓下載的目錄就能夠了,很是簡單。 安裝完成後,目錄以下:

目錄 說明 bin mycat命令,啓動、重啓、中止等 catlet catlet爲Mycat的一個擴展功能 conf Mycat 配置信息,重點關注 lib Mycat引用的jar包,Mycat是java開發的 logs 日誌文件,包括Mycat啓動的日誌和運行的日誌。 配置 Mycat的配置文件都在conf目錄裏面,這裏介紹幾個經常使用的文件:

文件 說明 server.xml Mycat的配置文件,設置帳號、參數等 schema.xml Mycat對應的物理數據庫和數據庫表的配置 rule.xml Mycat分片(分庫分表)規則 Mycat的架構其實很好理解,Mycat是代理,Mycat後面就是物理數據庫。和Web服務器的Nginx相似。對於使用者來講,訪問的都是Mycat,不會接觸到後端的數據庫。 咱們如今作一個主從、讀寫分離,簡單分表的示例。結構以下圖:

服務器 IP 說明 Mycat 192.168.0.2 mycat服務器,鏈接數據庫時,鏈接此服務器 database1 192.168.0.3 物理數據庫1,真正存儲數據的數據庫 database2 192.168.0.4 物理數據庫2,真正存儲數據的數據庫 Mycat做爲主數據庫中間件,確定是與代碼弱關聯的,因此代碼是不用修改的,使用Mycat後,鏈接數據庫是不變的,默認端口是8066。鏈接方式和普通數據庫同樣,如:jdbc:mysql://192.168.0.2:8066/

server.xml

示例

<user name="test"> <property name="password">test</property> <property name="schemas">lunch</property> <property name="readOnly">false</property>

<!-- 表級 DML 權限設置 -->
    <!--        
    <privileges check="false">
        <schema name="TESTDB" dml="0110" >
            <table name="tb01" dml="0000"></table>
            <table name="tb02" dml="1111"></table>
        </schema>
    </privileges>       
     -->
</user>

重點關注下面這段,其餘默認便可。

參數 說明 user 用戶配置節點 --name 登陸的用戶名,也就是鏈接Mycat的用戶名 --password 登陸的密碼,也就是鏈接Mycat的密碼 --schemas 數據庫名,這裏會和schema.xml中的配置關聯,多個用逗號分開,例如須要這個用戶須要管理兩個數據庫db1,db2,則配置db1,dbs --privileges 配置用戶針對表的增刪改查的權限,具體見文檔吧 我這裏配置了一個帳號test 密碼也是test,針對數據庫lunch,讀寫權限都有,沒有針對表作任何特殊的權限。

schema.xml schema.xml是最主要的配置項,首先看個人配置文件。

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 數據庫配置,與server.xml中的數據庫對應 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />
<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理數據庫配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

</mycat:schema> 參數 說明 schema 數據庫設置,此數據庫爲邏輯數據庫,name與server.xml中schema對應 dataNode 分片信息,也就是分庫相關配置 dataHost 物理數據庫,真正存儲數據的數據庫 每一個節點的屬性逐一說明:

schema:

屬性 說明 name 邏輯數據庫名,與server.xml中的schema對應 checkSQLschema 數據庫前綴相關設置,建議看文檔,這裏暫時設爲folse sqlMaxLimit select 時默認的limit,避免查詢全表 table:

屬性 說明 name 表名,物理數據庫中表名 dataNode 表存儲到哪些節點,多個節點用逗號分隔。節點爲下文dataNode設置的name primaryKey 主鍵字段名,自動生成主鍵時須要設置 autoIncrement 是否自增 rule 分片規則名,具體規則下文rule詳細介紹 dataNode

屬性 說明 name 節點名,與table中dataNode對應 datahost 物理數據庫名,與datahost中name對應 database 物理數據庫中數據庫名 dataHost

屬性 說明 name 物理數據庫名,與dataNode中dataHost對應 balance 均衡負載的方式 writeType 寫入方式 dbType 數據庫類型 heartbeat 心跳檢測語句,注意語句結尾的分號要加。 應用場景 數據庫分表分庫 配置以下:

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 數據庫配置,與server.xml中的數據庫對應 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />
<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理數據庫配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

</mycat:schema> 我在192.168.0.二、192.168.0.3均有數據庫lunch。 lunchmenu、restaurant、userlunch、users這些表都只寫入節點dn1,也就是192.168.0.2這個服務,而dictionary寫入了dn一、dn2兩個節點,也就是192.168.0.二、192.168.0.3這兩臺服務器。分片的規則爲:mod-long。 主要關注rule屬性,rule屬性的內容來源於rule.xml這個文件,Mycat支持10種分表分庫的規則,基本能知足你所須要的要求,這個必須贊一個,其餘數據庫中間件好像都沒有這麼多。 table中的rule屬性對應的就是rule.xml文件中tableRule的name,具體有哪些分表和分庫的實現,建議仍是看下文檔。我這裏選擇的mod-long就是將數據平均拆分。由於我後端是兩臺物理庫,因此rule.xml中mod-long對應的function count爲2,見下面部分代碼:

<tableRule name="mod-long"> <rule> <columns>id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule>

<function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">2</property> </function> 數據庫讀寫分離 配置以下:

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 數據庫配置,與server.xml中的數據庫對應 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1"  />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />

<!-- 物理數據庫配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    <readHost host="hostM1" url="192.168.0.3:3306" user="root" password="123456">   
    </readHost>
    </writeHost>
</dataHost>

</mycat:schema> 這樣的配置與前一個示例配置改動以下: 刪除了table分配的規則,以及datanode只有一個 datahost也只有一臺,可是writehost總添加了readhost,balance改成1,表示讀寫分離。 以上配置達到的效果就是102.168.0.2爲主庫,192.168.0.3爲從庫。

注意:Mycat主從分離只是在讀的時候作了處理,寫入數據的時候,只會寫入到writehost,須要經過mycat的主從複製將數據複製到readhost,這個問題當時候我糾結了很久,數據寫入writehost後,readhost一直沒有數據,覺得是本身配置的問題,後面才發現Mycat就沒有實現主從複製的功能,畢竟數據庫自己自帶的這個功能纔是最高效穩定的。

至於其餘的場景,如同時主從和分表分庫也是支持的了,只要瞭解這個實現之後再去修改配置,都是能夠實現的。而熱備及故障專業官方推薦使用haproxy配合一塊兒使用,你們能夠試試。

使用 Mycat的啓動也很簡單,啓動命令在Bin目錄:

##啓動 mycat start

##中止 mycat stop

##重啓 mycat restart 若是在啓動時發現異常,在logs目錄中查看日誌。

wrapper.log 爲程序啓動的日誌,啓動時的問題看這個 mycat.log 爲腳本執行時的日誌,SQL腳本執行報錯後的具體錯誤內容,查看這個文件。mycat.log是最新的錯誤日誌,歷史日誌會根據時間生成目錄保存。 mycat啓動後,執行命令不成功,可能實際上配置有錯誤,致使後面的命令沒有很好的執行。

Mycat帶來的最大好處就是使用是徹底不用修改原有代碼的,在mycat經過命令啓動後,你只須要將數據庫鏈接切換到Mycat的地址就能夠了。以下面就能夠進行鏈接了:

mysql -h192.168.0.1 -P8806 -uroot -p123456 鏈接成功後能夠執行sql腳本了。 因此,能夠直接經過sql管理工具(如:navicat、datagrip)鏈接,執行腳本。我一直用datagrip來進行平常簡單的管理,這個很方便。

Mycat還有一個管理的鏈接,端口號是9906.

mysql -h192.168.0.1 -P9906 -uroot -p123456 鏈接後能夠根據管理命令查看Mycat的運行狀況,固然,喜歡UI管理方式的人,能夠安裝一個Mycat-Web來進行管理,有興趣自行搜索。

簡而言之,開發中使用Mycat和直接使用Mysql機會沒有差異。

常見問題 使用Mycat後總會遇到一些坑,我將本身遇到的一些問題在這裏列一下,但願能與你們有共鳴:

Mycat是否是配置之後,就能徹底解決分表分庫和讀寫分離問題? Mycat配合數據庫自己的複製功能,能夠解決讀寫分離的問題,可是針對分表分庫的問題,不是完美的解決。或者說,至今爲止,業界沒有完美的解決方案。 分表分庫寫入能完美解決,可是,不能完美解決主要是聯表查詢的問題,Mycat支持兩個表聯表的查詢,多餘兩個表的查詢不支持。 其實,不少數據庫中間件關於分表分庫後查詢的問題,都是須要本身實現的,並且節本都不支持聯表查詢,Mycat已經算作地很是先進了。 分表分庫的後聯表查詢問題,你們經過合理數據庫設計來避免。

Mycat支持哪些數據庫,其餘平臺如 .net、PHP能用嗎? 官方說了,支持的數據庫包括MySQL、SQL Server、Oracle、DB二、PostgreSQL 等主流數據庫,很贊。 儘可能用Mysql,我試過SQL Server,會有些小問題,由於部分語法有點差別。

Mycat 非JAVA平臺如 .net、PHP能用嗎? 能夠用。這一點MyCat作的也很棒。

參考 《Mycat權威指南》: http://www.mycat.io/document/Mycat_V1.6.0.pdf 官網 :http://www.mycat.io/

相關文章
相關標籤/搜索