mysql 之 優化 (收集于網絡)

(以下內容均來自于網絡,如果有版權限制,請聯系我0.0)

Mysql存儲千億級的數據,是一項非常大的挑戰。Mysql單表可以存儲10億級的數據,只是這個時候性能非常差,項目中大量的實驗證明,Mysql單表容量在500萬左右,性能處于最佳狀態。

優化的順序是:

第一優化你的sql和索引;

第二加緩存 memcached,redis;

第三以上都做了后,還是慢,就做主從復制或主主復制,讀寫分離,可以在應用層做,效率高,也可以用三方工具,第三方工具推薦360的atlas,其它的要么效率不高,要么沒人維護;

第四如果以上都做了還是慢,不要想著去做切分,mysql自帶分區表,先試試這個,對你的應用是透明的,無需更改代碼,但是sql語句是需要針對分區表做優化的,sql條件中要帶上分區條件的列,從而使查詢定位到少量的分區上,否則就會掃描全部分區,另外分區表還有一些坑,在這里就不多說了;

第五如果以上都做了,那就先做垂直拆分,其實就是根據你模塊的耦合度,將一個大的系統分為多個小的系統,也就是分布式系統;

第六才是水平切分,針對數據量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key,為了有好的查詢效率,表結構也要改動,做一定的冗余,應用也要改,sql中盡量帶sharding key,將數據定位到限定的表上去查,而不是掃描全部的表;

mysql數據庫一般都是按照這個步驟去演化的,成本也是由低到高;

一、查詢優化

1、創建索引

有關索引的博客:https://blog.csdn.net/fenglepeng/article/details/103141756

最簡單也是最常用的優化就是查詢。因為對于CRUD操作,read操作是占據了絕大部分的比例,所以read的性能基本上決定了應用的性能。對于查詢性能最常用的就是創建索引。經過測試,2000萬條記錄,每條記錄200字節兩列varchar類型的。當不使用索引的時候查詢一條記錄需要一分鐘,而當創建了索引的時候查詢時間可以忽略。但是,當你在已有數據上添加索引的時候,則需要耗費非常大的時間。我插入2000萬條記錄之后,再創建索引大約話費了幾十分鐘的樣子。

創建索引的弊端和場合。雖然創建索引可以很大程度上優化查詢的速度,但是弊端也是很明顯的。一個是在插入數據的時候,創建索引也需要消耗部分的時間,這就使得插入性能在一定程度上降低;另一個很明顯的是數據文件變的更大。在列上創建索引的時候,每條索引的長度是和你創建列的時候制定的長度相同的。比如你創建varchar(100),當你在該列上創建索引,那么索引的長度則是102字節,因為長度超過64字節則會額外增加2字節記錄索引的長度。

從上圖可以看到我在YCSB_KEY這一列(長度100)上創建了一個名字為index_ycsb_key的索引,每條索引長度都為102,想象一下當數據變的巨大無比的時候,索引的大小也是不可以小覷的。而且從這也可以看出,索引的長度和列類型的長度還不同,比如varchar它是變長的字符類型(請看MySQL數據類型分析),實際存儲長度是是實際字符的大小,但是索引卻是你聲明的長度的大小。你創建列的時候聲明100字節,那么索引長度就是這個字節再加上2,它不管你實際存儲是多大。

除了創建索引需要消耗時間,索引文件體積會變的越來越大之外,創建索引也需要看的你存儲數據的特征。當你存儲數據很大一部分都是重復記錄,那這個時候創建索引是百害而無一利。所以,當很多數據重復的時候,索引帶來的查詢提升的效果是可以直接忽略的,但是這個時候你還要承受插入數據的時候創建索引帶來的性能消耗。

2、緩存的配置。

在MySQL中有多種多樣的緩存,有的緩存負責緩存查詢語句,也有的負責緩存查詢數據。這些緩存內容客戶端無法操作,是由server端來維護的。它會隨著你查詢與修改等相應不同操作進行不斷更新。通過其配置文件我們可以看到在MySQL中的緩存:

在這里主要分析query cache,它是主要用來緩存查詢數據。當你想使用該cache,必須把query_cache_size大小設置為非0。當設置大小為非0的時候,server就會緩存每次查詢返回的結果,到下次相同查詢server就直接從緩存獲取數據,而不是再執行查詢。能緩存的數據量就和你的size大小設置有關,所以當你設置的足夠大,數據可以完全緩存到內存,速度就會非常之快。

但是,query cache也有它的弊端。當你對數據表做任何的更新操作(update/insert/delete)等操作,server為了保證緩存與數據庫的一致性,會強制刷新緩存數據,導致緩存數據全部失效。所以,當一個表格的更新數據表操作非常多的話,query cache是不會起到查詢提升的性能,還會影響其他操作的性能。

3、slow_query_log分析。

其實對于查詢性能提升,最重要也是最根本的手段也是slow_query的設置。

當你設置slow_query_log為on的時候,server端會對每次的查詢進行記錄,當超過你設置的慢查詢時間 (long_query_time)的時候就把該條查詢記錄到日志。而你對性能進行優化的時候,就可以分析慢查詢日志,對慢查詢的查詢語句進行有目的的優化。可以通過創建各種索引,可以通過分表等操作。

4、分庫分表

分庫分表應該算是查詢優化的殺手锏了。上述各種措施在數據量達到一定等級之后,能起到優化的作用已經不明顯了。這個時候就必須對數據量進行分流。分流一般有分庫與分表兩種措施。而分表又有垂直切分與水平切分兩種方式。

對于mysql,其數據文件是以文件形式存儲在磁盤上的。當一個數據文件過大的時候,操作系統對大文件的操作就會比較麻煩與耗時,而且有的操作系統就不支持大文件,所以這個時候就必須分表了。另外對于mysql常用的存儲引擎是Innodb,它的底層數據結構是B+樹。當其數據文件過大的時候,B+樹就會從層次和節點上比較多,當查詢一個節點的時候可能會查詢很多層次,而這必定會導致多次IO操作進行裝載進內存,肯定會耗時的。除此之外還有Innodb對于B+樹的鎖機制。對每個節點進行加鎖,那么當更改表結構的時候,這時候就會樹進行加鎖,當表文件大的時候,這可以認為是不可實現的。?

所以綜上我們就必須進行分表與分庫的操作。

5、子查詢優化

在查詢中經常會用到子查詢,在子查詢的時候一般使用in或者exist關鍵詞。針對in和exist在查詢的時候當數據量大到一定程度以后,查詢執行時間就差別比較大。但是,為了避免此類情況出現,最好的方式是使用join查詢。因為在絕大多數情況下,服務器對join的查詢優化要遠遠高于子查詢優化。在比較高的版本5.6,mysql查詢會自動把in查詢優化成join查詢,就不會出現子查詢比較慢的問題。有時候也可以采用distinct關鍵詞來限制子查詢的數量,但是需要注意的是distinct很多時候會轉化為group by,這個時候就會出現一個?臨時表,就會出現copy數據到臨時表的時延。

更多的子查詢優化?請點擊。

分表

如何進行分庫分表,目前互聯網上有許多的版本,比較知名的一些方案:阿里的TDDL,DRDS和cobar,京東金融的sharding-jdbc;民間組織的MyCAT;360的Atlas;美團的zebra;其他比如網易,58,京東等公司都有自研的中間件。

這么多的分庫分表中間件方案歸總起來,就兩類:client模式和proxy模式。

client模式

proxy模式

無論是client模式,還是proxy模式。幾個核心的步驟是一樣的:SQL解析,重寫,路由,執行,結果歸并。個人比較傾向于采用client模式,它架構簡單,性能損耗也比較小,運維成本低。

如何對業務類型進行分庫分表。分庫分表最重要的一步,即sharding column的選取,sharding column選擇的好壞將直接決定整個分庫分表方案最終是否成功。而sharding column的選取跟業務強相關。在我們的項目場景中,sharding column無疑最好的選擇是業務編號。通過業務編號,將客戶不同的綁定簽約業務保存到不同的表里面去,根據業務編號路由到相應的表中進行查詢,達到進一步優化sql的目的。

記錄一次MySQL兩千萬數據的大表優化解決過程,提供三種解決方案(轉)

問題概述

使用阿里云rds for MySQL數據庫(就是MySQL5.6版本),有個用戶上網記錄表6個月的數據量近2000萬,保留最近一年的數據量達到4000萬,查詢速度極慢,日常卡死。嚴重影響業務。

問題前提:老系統,當時設計系統的人大概是大學沒畢業,表設計和sql語句寫的不僅僅是垃圾,簡直無法直視。原開發人員都已離職,到我來維護。

方案概述

方案一:優化現有mysql數據庫。優點:不影響現有業務,源程序不需要修改代碼,成本最低。缺點:有優化瓶頸,數據量過億就玩完了。

方案二:升級數據庫類型,換一種100%兼容mysql的數據庫。優點:不影響現有業務,源程序不需要修改代碼,你幾乎不需要做任何操作就能提升數據庫性能,缺點:多花錢

方案三:一步到位,大數據解決方案,更換newsql/nosql數據庫。優點:擴展性強,成本低,沒有數據容量瓶頸,缺點:需要修改源程序代碼

以上三種方案,按順序使用即可,數據量在億級別一下的沒必要換nosql,開發成本太高。三種方案我都試了一遍,而且都形成了落地解決方案

方案一詳細說明:優化現有mysql數據庫

跟阿里云數據庫大佬電話溝通 and Google解決方案 and 問群里大佬,總結如下(都是精華):

1.數據庫設計和表創建時就要考慮性能

mysql數據庫本身高度靈活,造成性能不足,嚴重依賴開發人員能力。也就是說開發人員能力高,則mysql性能高。這也是很多關系型數據庫的通病,所以公司的dba通常工資巨高。

設計表時要注意:

  • 表字段避免null值出現,null值很難查詢優化且占用額外的索引空間,推薦默認數字0代替null。
  • 盡量使用INT而非BIGINT,如果非負則加上UNSIGNED(這樣數值容量會擴大一倍),當然能使用TINYINT、SMALLINT、MEDIUM_INT更好。
  • 使用枚舉或整數代替字符串類型
  • 盡量使用TIMESTAMP而非DATETIME
  • 單表不要有太多字段,建議在20以內
  • 用整型來存IP

索引

  • 索引并不是越多越好,要根據查詢有針對性的創建,考慮在WHERE和ORDER BY命令上涉及的列建立索引,可根據EXPLAIN來查看是否用了索引還是全表掃描
  • 應盡量避免在WHERE子句中對字段進行NULL值判斷,否則將導致引擎放棄使用索引而進行全表掃描
  • 值分布很稀少的字段不適合建索引,例如"性別"這種只有兩三個值的字段
  • 字符字段只建前綴索引
  • 字符字段最好不要做主鍵
  • 不用外鍵,由程序保證約束
  • 盡量不用UNIQUE,由程序保證約束
  • 使用多列索引時主意順序和查詢條件保持一致,同時刪除不必要的單列索引

簡言之就是使用合適的數據類型,選擇合適的索引

2.sql的編寫需要注意優化

  • 使用limit對查詢結果的記錄進行限定
  • 避免select *,將需要查找的字段列出來
  • 使用連接(join)來代替子查詢
  • 拆分大的delete或insert語句
  • 可通過開啟慢查詢日志來找出較慢的SQL
  • 不做列運算:SELECT id WHERE age + 1 = 10,任何對列的操作都將導致表掃描,它包括數據庫教程函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊
  • sql語句盡可能簡單:一條sql只能在一個cpu運算;大語句拆小語句,減少鎖時間;一條大sql可以堵死整個庫
  • OR改寫成IN:OR的效率是n級別,IN的效率是log(n)級別,in的個數建議控制在200以內
  • 不用函數和觸發器,在應用程序實現
  • 避免%xxx式查詢
  • 少用JOIN
  • 使用同類型進行比較,比如用'123'和'123'比,123和123比
  • 盡量避免在WHERE子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描
  • 對于連續數值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
  • 列表數據不要拿全表,要使用LIMIT來分頁,每頁數量也不要太大

引擎

目前廣泛使用的是MyISAM和InnoDB兩種引擎:

MyISAM引擎是MySQL 5.1及之前版本的默認引擎,它的特點是:

  • 不支持行鎖,讀取時對需要讀到的所有表加鎖,寫入時則對表加排它鎖
  • 不支持事務
  • 不支持外鍵
  • 不支持崩潰后的安全恢復
  • 在表有讀取查詢的同時,支持往表中插入新紀錄
  • 支持BLOB和TEXT的前500個字符索引,支持全文索引
  • 支持延遲更新索引,極大提升寫入性能
  • 對于不會進行修改的表,支持壓縮表,極大減少磁盤空間占用

InnoDB在MySQL 5.5后成為默認索引,它的特點是:

  • 支持行鎖,采用MVCC來支持高并發
  • 支持事務
  • 支持外鍵
  • 支持崩潰后的安全恢復
  • 不支持全文索引

總體來講,MyISAM適合SELECT密集型的表,而InnoDB適合INSERT和UPDATE密集型的表

MyISAM速度可能超快,占用存儲空間也小,但是程序要求事務支持,故InnoDB是必須的,故該方案無法執行,放棄!

3.分區

MySQL在5.1版引入的分區是一種簡單的水平拆分,用戶需要在建表的時候加上分區參數,對應用是透明的無需修改代碼

對用戶來說,分區表是一個獨立的邏輯表,但是底層由多個物理子表組成,實現分區的代碼實際上是通過對一組底層表的對象封裝,但對SQL層來說是一個完全封裝底層的黑盒子。MySQL實現分區的方式也意味著索引也是按照分區的子表定義,沒有全局索引

用戶的SQL語句是需要針對分區表做優化,SQL條件中要帶上分區條件的列,從而使查詢定位到少量的分區上,否則就會掃描全部分區,可以通過EXPLAIN PARTITIONS來查看某條SQL語句會落在那些分區上,從而進行SQL優化,我測試,查詢時不帶分區條件的列,也會提高速度,故該措施值得一試。

分區的好處是:

  • 可以讓單表存儲更多的數據
  • 分區表的數據更容易維護,可以通過清楚整個分區批量刪除大量數據,也可以增加新的分區來支持新插入的數據。另外,還可以對一個獨立分區進行優化、檢查、修復等操作
  • 部分查詢能夠從查詢條件確定只落在少數分區上,速度會很快
  • 分區表的數據還可以分布在不同的物理設備上,從而搞笑利用多個硬件設備
  • 可以使用分區表賴避免某些特殊瓶頸,例如InnoDB單個索引的互斥訪問、ext3文件系統的inode鎖競爭
  • 可以備份和恢復單個分區

分區的限制和缺點:

  • 一個表最多只能有1024個分區
  • 如果分區字段中有主鍵或者唯一索引的列,那么所有主鍵列和唯一索引列都必須包含進來
  • 分區表無法使用外鍵約束
  • NULL值會使分區過濾無效
  • 所有分區必須使用相同的存儲引擎

分區的類型:

  • RANGE分區:基于屬于一個給定連續區間的列值,把多行分配給分區
  • LIST分區:類似于按RANGE分區,區別在于LIST分區是基于列值匹配一個離散值集合中的某個值來進行選擇
  • HASH分區:基于用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含MySQL中有效的、產生非負整數值的任何表達式
  • KEY分區:類似于按HASH分區,區別在于KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值

我首先根據月份把上網記錄表RANGE分區了12份,查詢效率提高6倍左右,效果不明顯,故:換id為HASH分區,分了64個分區,查詢速度提升顯著。問題解決!

4.分表

分表就是把一張大表,按照如上過程都優化了,還是查詢卡死,那就把這個表分成多張表,把一次查詢分成多次查詢,然后把結果組合返回給用戶。

分表分為垂直拆分和水平拆分,通常以某個字段做拆分項。比如以id字段拆分為100張表: 表名為 tableName_id%100

但:分表需要修改源程序代碼,會給開發帶來大量工作,極大的增加了開發成本,故:只適合在開發初期就考慮到了大量數據存在,做好了分表處理,不適合應用上線了再做修改,成本太高!!!而且選擇這個方案,都不如選擇我提供的第二第三個方案的成本低!故不建議采用。

5.分庫

把一個數據庫分成多個,建議做個讀寫分離就行了,真正的做分庫也會帶來大量的開發成本,得不償失!不推薦使用。

方案二詳細說明:升級數據庫,換一個100%兼容mysql的數據庫

mysql性能不行,那就換個。為保證源程序代碼不修改,保證現有業務平穩遷移,故需要換一個100%兼容mysql的數據庫。

開源選擇

1.tiDB https://github.com/pingcap/tidb

2.Cubrid https://www.cubrid.org/

3.開源數據庫會帶來大量的運維成本且其工業品質和MySQL尚有差距,有很多坑要踩,如果你公司要求必須自建數據庫,那么選擇該類型產品。

云數據選擇

阿里云POLARDB

https://www.aliyun.com/product/polardb?spm=a2c4g.11174283.cloudEssentials.47.7a984b5cS7h4wH

官方介紹語:POLARDB 是阿里云自研的下一代關系型分布式云原生數據庫,100%兼容MySQL,存儲容量最高可達 100T,性能最高提升至 MySQL 的 6 倍。POLARDB 既融合了商業數據庫穩定、可靠、高性能的特征,又具有開源數據庫簡單、可擴展、持續迭代的優勢,而成本只需商用數據庫的 1/10。

我開通測試了一下,支持免費mysql的數據遷移,無操作成本,性能提升在10倍左右,價格跟rds相差不多,是個很好的備選解決方案!

阿里云OcenanBase

淘寶使用的,扛得住雙十一,性能卓著,但是在公測中,我無法嘗試,但值得期待

阿里云HybridDB for MySQL (原PetaData)

https://www.aliyun.com/product/petadata?spm=a2c4g.11174283.cloudEssentials.54.7a984b5cS7h4wH

官方介紹:云數據庫HybridDB for MySQL (原名PetaData)是同時支持海量數據在線事務(OLTP)和在線分析(OLAP)的HTAP(Hybrid Transaction/Analytical Processing)關系型數據庫。

我也測試了一下,是一個olap和oltp兼容的解決方案,但是價格太高,每小時高達10塊錢,用來做存儲太浪費了,適合存儲和分析一起用的業務。

騰訊云DCDB

https://cloud.tencent.com/product/dcdb_for_tdsql

官方介紹:DCDB又名TDSQL,一種兼容MySQL協議和語法,支持自動水平拆分的高性能分布式數據庫——即業務顯示為完整的邏輯表,數據卻均勻的拆分到多個分片中;每個分片默認采用主備架構,提供災備、恢復、監控、不停機擴容等全套解決方案,適用于TB或PB級的海量數據場景。

騰訊的我不喜歡用,不多說。原因是出了問題找不到人,線上問題無法解決頭疼!但是他價格便宜,適合超小公司,玩玩。

方案三詳細說明:去掉mysql,換大數據引擎處理數據

開源解決方案

hadoop家族。hbase/hive懟上就是了。但是有很高的運維成本,一般公司是玩不起的,沒十萬投入是不會有很好的產出的!

云解決方案

這個就比較多了,也是一種未來趨勢,大數據由專業的公司提供專業的服務,小公司或個人購買服務,大數據就像水/電等公共設施一樣,存在于社會的方方面面。國內做的最好的當屬阿里云。

我選擇了阿里云的MaxCompute配合DataWorks,使用超級舒服,按量付費,成本極低。

MaxCompute可以理解為開源的Hive,提供sql/mapreduce/ai算法/python腳本/shell腳本等方式操作數據,數據以表格的形式展現,以分布式方式存儲,采用定時任務和批處理的方式處理數據。DataWorks提供了一種工作流的方式管理你的數據處理任務和調度監控。

當然你也可以選擇阿里云hbase等其他產品,我這里主要是離線處理,故選擇MaxCompute,基本都是圖形界面操作,大概寫了300行sql,費用不超過100塊錢就解決了數據處理問題。

千萬條數據優化建議30條

1、對查詢進行優化、應盡量避免全表掃描、首先應考慮在 where 及 order by 涉及的列上建立索引。

2、應盡量避免在 where 子句中對字段進行 null 值判斷、否則將導致引擎放棄使用索引而進行全表掃描、如:

select id from t where num is null;

--可以在num上設置默認值0、確保表中num列沒有null值、然后這樣查詢:

select id from t where num=0;

3、應盡量避免在 where 子句中使用!=或<>操作符、否則將引擎放棄使用索引而進行全表掃描。

4、應盡量避免在 where 子句中使用 or 來連接條件、否則將導致引擎放棄使用索引而進行全表掃描、如:

select id from t where num=10 or num=20

--可以這樣查詢:

select id from t where num=10 union all select id from t where num=20;

5、in 和 not in 也要慎用、否則會導致全表掃描、如:

select id from t where num in(1,2,3);

對于連續的數值、能用 between 就不要用 in 了:

select id from t where num between 1 and 3;

6、下面的查詢也將導致全表掃描:

select id from t where name like '%abc%';

--若要提高效率、可以考慮全文檢索。

7、如果在 where 子句中使用參數、也會導致全表掃描。因為SQL只有在運行時才會解析局部變量、但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而、如果在編譯時建立訪問計劃、變量的值還是未知的、因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:

select id from t where num=@num

--可以改為強制查詢使用索引:

select id from t with(index(索引名)) where num=?@num?;

8、應盡量避免在 where 子句中對字段進行表達式操作、這將導致引擎放棄使用索引而進行全表掃描。如:

select id from t where num/2=100;

--應改為:

select id from t where num=100*2;

9、應盡量避免在where子句中對字段進行函數操作、這將導致引擎放棄使用索引而進行全表掃描。如:

select id from t where substring(name,1,3)='abc';? --name以abc開頭的id

select id from t where datediff(day,createdate,'2005-11-30')=0;? --‘2005-11-30’生成的id

--應改為:

select id from t where name like 'abc%';

select id from t where createdate>='2005-11-30' and createdate<'2005-12-1';

10、不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算、否則系統將可能無法正確使用索引。

11、在使用索引字段作為條件時、如果該索引是復合索引、那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引、否則該索引將不會被使用、并且應盡可能的讓字段順序與索引順序相一致。

12、不要寫一些沒有意義的查詢、如需要生成一個空表結構:

select col1,col2 into #t from t where 1=0;? --這類代碼不會返回任何結果集、但是會消耗系統資源的、應改成這樣:

create table #t(...);

13、很多時候用 exists 代替 in 是一個好的選擇:

select num from a where num in(select num from b);

--用下面的語句替換:

select num from a where exists(select 1 from b where num=a.num);

14、并不是所有索引對查詢都有效、SQL是根據表中數據來進行查詢優化的、當索引列有大量數據重復時、SQL查詢可能不會去利用索引、如一表中有字段sex、male、female幾乎各一半、那么即使在sex上建了索引也對查詢效率起不了作用。

15、索引并不是越多越好、索引固然可以提高相應的 select 的效率、但同時也降低了 insert 及 update 的效率、因為 insert 或 update 時有可能會重建索引、所以怎樣建索引需要慎重考慮、視具體情況而定。一個表的索引數最好不要超過6個、若太多則應考慮一些不常使用到的列上建的索引是否有必要。

16、應盡可能的避免更新 clustered 索引數據列、因為 clustered 索引數據列的順序就是表記錄的物理存儲順序、一旦該列值改變將導致整個表記錄的順序的調整、會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列、那么需要考慮是否應將該索引建為 clustered 索引。

17、盡量使用數字型字段、若只含數值信息的字段盡量不要設計為字符型、這會降低查詢和連接的性能、并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符、而對于數字型而言只需要比較一次就夠了。

18、盡可能的使用 varchar/nvarchar 代替 char/nchar 、因為首先變長字段存儲空間小、可以節省存儲空間、其次對于查詢來說、在一個相對較小的字段內搜索效率顯然要高些。

19、任何地方都不要使用 select * from t 、用具體的字段列表代替“*”、不要返回用不到的任何字段。

20、盡量使用表變量來代替臨時表。如果表變量包含大量數據、請注意索引非常有限(只有主鍵索引)。

21、避免頻繁創建和刪除臨時表、以減少系統表資源的消耗。

22、臨時表并不是不可使用、適當地使用它們可以使某些例程更有效、例如、當需要重復引用大型表或常用表中的某個數據集時。但是、對于一次性事件、最好使用導出表。

23、在新建臨時表時、如果一次性插入數據量很大、那么可以使用 select into 代替 create table、避免造成大量 log 、以提高速度;如果數據量不大、為了緩和系統表的資源、應先create table、然后insert。

24、如果使用到了臨時表、在存儲過程的最后務必將所有的臨時表顯式刪除、先 truncate table 、然后 drop table 、這樣可以避免系統表的較長時間鎖定。

25、盡量避免使用游標、因為游標的效率較差、如果游標操作的數據超過1萬行、那么就應該考慮改寫。

26、使用基于游標的方法或臨時表方法之前、應先尋找基于集的解決方案來解決問題、基于集的方法通常更有效。

27、與臨時表一樣、游標并不是不可使用。對小型數據集使用 FAST_FORWARD 游標通常要優于其他逐行處理方法、尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時間允許、基于游標的方法和基于集的方法都可以嘗試一下、看哪一種方法的效果更好。

28、在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON 、在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句后向客戶端發送 DONE_IN_PROC 消息。

29、盡量避免大事務操作、提高系統并發能力。

30、盡量避免向客戶端返回大數據量、若數據量過大、應該考慮相應需求是否合理。

MySQL 性能優化的建議

1. 為查詢緩存優化你的查詢

大多數的MySQL服務器都開啟了查詢緩存。這是提高性最有效的方法之一,而且這是被MySQL的數據庫引擎處理的。當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到一個緩存中,這樣后續的相同的查詢就不用操作表而直接訪問緩存結果了。這里最主要的問題是,對于程序員來說,這個事情是很容易被忽略的。因為,我們某些查詢語句會讓MySQL不使用緩存。請看下面的示例:

// 查詢緩存不開啟
$r?= mysql_query(?"SELECT username FROM user WHERE signup_date >= CURDATE()"?);// 開啟查詢緩存
$today?=?date?(?"Y-m-d"?);
$r?= mysql_query(?"SELECT username FROM user WHERE signup_date >= '$today'"?);

上面兩條SQL語句的差別就是 CURDATE() ,MySQL的查詢緩存對這個函數不起作用。所以,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數都不會開啟查詢緩存,因為這些函數的返回是會不定的易變的。所以,你所需要的就是用一個變量來代替MySQL的函數,從而開啟緩存。

2. EXPLAIN 你的 SELECT 查詢

EXPLAIN 博客https://blog.csdn.net/fenglepeng/article/details/103392319

使用?EXPLAIN?關鍵字可以讓你知道MySQL是如何處理你的SQL語句的。這可以幫你分析你的查詢語句或是表結構的性能瓶頸。

EXPLAIN 的查詢結果還會告訴你你的索引主鍵被如何利用的,你的數據表是如何被搜索和排序的……等等。

3. 當只要一行數據時使用 LIMIT 1

當你查詢表的有些時候,你已經知道結果只會有一條結果,但因為你可能需要去fetch游標,或是你也許會去檢查返回的記錄數。在這種情況下,加上 LIMIT 1 可以增加性能。這樣一樣,MySQL數據庫引擎會在找到一條數據后停止搜索,而不是繼續往后查少下一條符合記錄的數據。下面的示例,只是為了找一下是否有“中國”的用戶,很明顯,后面的會比前面的更有效率。(第一條中是Select *,第二條是Select 1)

// 沒有效率的:
$r = mysql_query( "SELECT * FROM user WHERE country = 'China'" );
if (mysql_num_rows( $r ) > 0) {// ...
}// 有效率的:
$r = mysql_query( "SELECT 1 FROM user WHERE country = 'China' LIMIT 1" );
if (mysql_num_rows( $r ) > 0) {// ...
}

4. 為搜索字段建索引

索引并不一定就是給主鍵或是唯一的字段。如果在你的表中,有某個字段你總要會經常用來做搜索,那么,請為其建立索引吧。

從上圖你可以看到那個搜索字串 “last_name LIKE ‘a%’”,一個是建了索引,一個是沒有索引,性能差了4倍左右。另外,你應該也需要知道什么樣的搜索是不能使用正常的索引的。例如,當你需要在一篇大的文章中搜索一個詞時,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是沒有意義的。你可能需要使用MySQL 全文索引?或是自己做一個索引(比如說:搜索關鍵詞或是Tag什么的)

5. 在Join表的時候使用相當類型的列,并將其索引

如果你的應用程序有很多 JOIN 查詢,你應該確認兩個表中Join的字段是被建過索引的。這樣,MySQL內部會啟動為你優化Join的SQL語句的機制。而且,這些被用來Join的字段,應該是相同的類型的。例如:如果你要把 DECIMAL 字段和一個 INT 字段Join在一起,MySQL就無法使用它們的索引。對于那些STRING類型,還需要有相同的字符集才行。(兩個表的字符集有可能不一樣)

// 在state中查找company
$r?= mysql_query("SELECT company_name FROM usersLEFT JOIN companies ON (users.state = companies.state)WHERE users.id =?$user_id?");// 兩個 state 字段應該是被建過索引的,而且應該是相當的類型,相同的字符集。

千萬不要 ORDER BY RAND()

想打亂返回的數據行?隨機挑一個數據?真不知道誰發明了這種用法,但很多新手很喜歡這樣用。但你確不了解這樣做有多么可怕的性能問題。如果你真的想把返回的數據行打亂了,你有N種方法可以達到這個目的。這樣使用只讓你的數據庫的性能呈指數級的下降。這里的問題是:MySQL會不得 不去執行RAND()函數(很耗CPU時間),而且這是為了每一行記錄去記行,然后再對其排序。就算是你用了Limit 1也無濟于事(因為要排序)

下面的示例是隨機挑一條記錄

// 千萬不要這樣做:
$r?= mysql_query(?"SELECT username FROM user ORDER BY RAND() LIMIT 1"?);// 這要會更好:
$r?= mysql_query(?"SELECT count(*) FROM user"?);
$d?= mysql_fetch_row(?$r?);
$rand?= mt_rand(0,?$d?[0] - 1);
$r?= mysql_query(?"SELECT username FROM user LIMIT $rand, 1"?);

7. 避免 SELECT *。

從數據庫里讀出越多的數據,那么查詢就會變得越慢。并且,如果你的數據庫服務器和WEB服務器是兩臺獨立的服務器的話,這還會增加網絡傳輸的負載。所以,你應該養成一個需要什么就取什么的好的習慣。

// 不推薦
$r?= mysql_query(?"SELECT * FROM user WHERE user_id = 1"?);
$d?= mysql_fetch_assoc(?$r?);
echo?"Welcome {$d['username']}"?;// 推薦
$r?= mysql_query(?"SELECT username FROM user WHERE user_id = 1"?);
$d?= mysql_fetch_assoc(?$r?);
echo?"Welcome {$d['username']}"?;

8.永遠為每張表設置一個ID

我們應該為數據庫里的每張表都設置一個ID做為其主鍵,而且最好的是一個INT型的(推薦使用UNSIGNED),并設置上自動增加的 AUTO_INCREMENT標志。就算是你 users 表有一個主鍵叫 “email”的字段,你也別讓它成為主鍵。使用 VARCHAR 類型來當主鍵會使用得性能下降。另外,在你的程序中,你應該使用表的ID來構造你的數據結構。而且,在MySQL數據引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設置變得非常重要,比如,集群,分區……在這里,只有一個情況是例外,那就是“關聯表”的“外鍵”,也就是說,這個表的主鍵,通過若干個別的表的主鍵構成。我們把這個情況叫做“外鍵”。比 如:有一個“學生表”有學生的ID,有一個“課程表”有課程ID,那么,“成績表”就是“關聯表”了,其關聯了學生表和課程表,在成績表中,學生ID和課 程ID叫“外鍵”其共同組成主鍵。

9. 使用 ENUM 而不是 VARCHAR

ENUM?類型是非常快和緊湊的。在實際上,其保存的是 TINYINT,但其外表上顯示為字符串。這樣一來,用這個字段來做一些選項列表變得相當的完美。

如果你有一個字段,比如“性別”,“國家”,“民族”,“狀態”或“部門”,你知道這些字段的取值是有限而且固定的,那么,你應該使用 ENUM 而不是 VARCHAR。

MySQL也有一個“建議”(見第十條)告訴你怎么去重新組織你的表結構。當你有一個 VARCHAR 字段時,這個建議會告訴你把其改成 ENUM 類型。使用 PROCEDURE ANALYSE() 你可以得到相關的建議。

10. 從 PROCEDURE ANALYSE() 取得建議

PROCEDURE ANALYSE()?會讓 MySQL 幫你去分析你的字段和其實際的數據,并會給你一些有用的建議。只有表中有實際的數據,這些建議才會變得有用,因為要做一些大的決定是需要有數據作為基礎 的。

例如,如果你創建了一個 INT 字段作為你的主鍵,然而并沒有太多的數據,那么,PROCEDURE ANALYSE()會建議你把這個字段的類型改成 MEDIUMINT 。或是你使用了一個 VARCHAR 字段,因為數據不多,你可能會得到一個讓你把它改成 ENUM 的建議。這些建議,都是可能因為數據不夠多,所以決策做得就不夠準。

在phpmyadmin里,你可以在查看表時,點擊 “Propose table structure” 來查看這些建議

一定要注意,這些只是建議,只有當你的表里的數據越來越多時,這些建議才會變得準確。一定要記住,你才是最終做決定的人。

11. 盡可能的使用 NOT NULL

除非你有一個很特別的原因去使用 NULL 值,你應該總是讓你的字段保持 NOT NULL。這看起來好像有點爭議,請往下看。

首先,問問你自己“Empty”和“NULL”有多大的區別(如果是INT,那就是0和NULL)?如果你覺得它們之間沒有什么區別,那么你就不要 使用NULL。(你知道嗎?在 Oracle 里,NULL 和 Empty 的字符串是一樣的!)

不要以為 NULL 不需要空間,其需要額外的空間,并且,在你進行比較的時候,你的程序會更復雜。 當然,這里并不是說你就不能使用NULL了,現實情況是很復雜的,依然會有些情況下,你需要使用NULL值。

下面摘自MySQL自己的文檔:

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

12. Prepared Statements

Prepared Statements很像存儲過程,是一種運行在后臺的SQL語句集合,我們可以從使用 prepared statements 獲得很多好處,無論是性能問題還是安全問題。

Prepared Statements 可以檢查一些你綁定好的變量,這樣可以保護你的程序不會受到“SQL注入式”攻擊。當然,你也可以手動地檢查你的這些變量,然而,手動的檢查容易出問題, 而且很經常會被程序員忘了。當我們使用一些framework或是ORM的時候,這樣的問題會好一些。

在性能方面,當一個相同的查詢被使用多次的時候,這會為你帶來可觀的性能優勢。你可以給這些Prepared Statements定義一些參數,而MySQL只會解析一次。

雖然最新版本的MySQL在傳輸Prepared Statements是使用二進制形勢,所以這會使得網絡傳輸非常有效率。

當然,也有一些情況下,我們需要避免使用Prepared Statements,因為其不支持查詢緩存。但據說版本5.1后支持了。

在PHP中要使用prepared statements,你可以查看其使用手冊:mysqli 擴展?或是使用數據庫抽象層,如:?PDO?.

// 創建 prepared statement
if?(?$stmt?=?$mysqli?->prepare(?"SELECT username FROM user WHERE state=?"?)) {// 綁定參數$stmt?->bind_param(?"s"?,?$state?);// 執行$stmt?->execute();// 綁定結果$stmt?->bind_result(?$username?);// 移動游標$stmt?->fetch();printf(?"%s is from %s\n"?,?$username?,?$state?);$stmt?->close();
}

正常的情況下,當你在當你在你的腳本中執行一個SQL語句的時候,你的程序會停在那里直到沒這個SQL語句返回,然后你的程序再往下繼續執行。你可 以使用無緩沖查詢來改變這個行為。13. 無緩沖的查詢

關于這個事情,在PHP的文檔中有一個非常不錯的說明:?mysql_unbuffered_query()?函數:

“mysql_unbuffered_query() sends the SQL query query to MySQL without automatically fetching and buffering the result rows as mysql_query() does. This saves a considerable amount of memory with SQL queries that produce large result sets, and you can start working on the result set immediately after the first row has been retrieved as you don’t have to wait until the complete SQL query has been performed.”

上面那句話翻譯過來是說,mysql_unbuffered_query() 發送一個SQL語句到MySQL而并不像mysql_query()一樣去自動fethch和緩存結果。這會相當節約很多可觀的內存,尤其是那些會產生大 量結果的查詢語句,并且,你不需要等到所有的結果都返回,只需要第一行數據返回的時候,你就可以開始馬上開始工作于查詢結果了。

然而,這會有一些限制。因為你要么把所有行都讀走,或是你要在進行下一次的查詢前調用?mysql_free_result()清除結果。而且,?mysql_num_rows()?或?mysql_data_seek()?將無法使用。所以,是否使用無緩沖的查詢你需要仔細考慮。

14. 把IP地址存成 UNSIGNED INT

很多程序員都會創建一個 VARCHAR(15) 字段來存放字符串形式的IP而不是整形的IP。如果你用整形來存放,只需要4個字節,并且你可以有定長的字段。而且,這會為你帶來查詢上的優勢,尤其是當 你需要使用這樣的WHERE條件:IP between ip1 and ip2。

我們必需要使用UNSIGNED INT,因為 IP地址會使用整個32位的無符號整形。

而你的查詢,你可以使用?INET_ATON()?來把一個字符串IP轉成一個整形,并使用?INET_NTOA()?把一個整形轉成一個字符串IP。在PHP中,也有這樣的函數?ip2long()?和?long2ip()?。

$r?=?"UPDATE users SET ip = INET_ATON('{$_SERVER['REMOTE_ADDR']}') WHERE user_id = $user_id"?;

15. 固定長度的表會更快

如果表中的所有字段都是“固定長度”的,整個表會被認為是?“static” 或 “fixed-length”?。 例如,表中沒有如下類型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一個這些字段,那么這個表就不是“固定長度靜態表”了,這樣,MySQL 引擎會用另一種方法來處理。

固定長度的表會提高性能,因為MySQL搜尋得會更快一些,因為這些固定的長度是很容易計算下一個數據的偏移量的,所以讀取的自然也會很快。而如果 字段不是定長的,那么,每一次要找下一條的話,需要程序找到主鍵。

并且,固定長度的表也更容易被緩存和重建。不過,唯一的副作用是,固定長度的字段會浪費一些空間,因為定長的字段無論你用不用,他都是要分配那么多 的空間。

使用“垂直分割”技術(見下一條),你可以分割你的表成為兩個一個是定長的,一個則是不定長的。

16. 垂直分割

“垂直分割”是一種把數據庫中的表按列變成幾張表的方法,這樣可以降低表的復雜度和字段的數目,從而達到優化的目的。(以前,在銀行做過項目,見過 一張表有100多個字段,很恐怖)

示例一?:在Users表中有一個字段是家庭地址,這個字段是可選字段,相比起,而且你在數據庫操作的時候除了個 人信息外,你并不需要經常讀取或是改寫這個字段。那么,為什么不把他放到另外一張表中呢? 這樣會讓你的表有更好的性能,大家想想是不是,大量的時候,我對于用戶表來說,只有用戶ID,用戶名,口令,用戶角色等會被經常使用。小一點的表總是會有 好的性能。

示例二?: 你有一個叫 “last_login” 的字段,它會在每次用戶登錄時被更新。但是,每次更新時會導致該表的查詢緩存被清空。所以,你可以把這個字段放到另一個表中,這樣就不會影響你對用戶 ID,用戶名,用戶角色的不停地讀取了,因為查詢緩存會幫你增加很多性能。

另外,你需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去Join他們,不然的話,這樣的性能會比不分割時還要差,而且,會是極數級 的下降。

17. 拆分大的 DELETE 或 INSERT 語句

如果你需要在一個在線的網站上去執行一個大的 DELETE 或 INSERT 查詢,你需要非常小心,要避免你的操作讓你的整個網站停止相應。因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。

Apache 會有很多的子進程或線程。所以,其工作起來相當有效率,而我們的服務器也不希望有太多的子進程,線程和數據庫鏈接,這是極大的占服務器資源的事情,尤其是 內存。

如果你把你的表鎖上一段時間,比如30秒鐘,那么對于一個有很高訪問量的站點來說,這30秒所積累的訪問進程/線程,數據庫鏈接,打開的文件數,可 能不僅僅會讓你泊WEB服務Crash,還可能會讓你的整臺服務器馬上掛了。

所以,如果你有一個大的處理,你定你一定把其拆分,使用 LIMIT 條件是一個好的方法。下面是一個示例:

while?(1) {//每次只做1000條mysql_query(?"DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000"?);if?(mysql_affected_rows() == 0) {// 沒得可刪了,退出!break?;}// 每次都要休息一會兒usleep(50000);
}

18. 越小的列會越快

對于大多數的數據庫引擎來說,硬盤操作可能是最重大的瓶頸。所以,把你的數據變得緊湊會對這種情況非常有幫助,因為這減少了對硬盤的訪問。

參看 MySQL 的文檔?Storage Requirements?查看所有的數據類型。

如果一個表只會有幾列罷了(比如說字典表,配置表),那么,我們就沒有理由使用 INT 來做主鍵,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 會更經濟一些。如果你不需要記錄時間,使用 DATE 要比 DATETIME 好得多。

當然,你也需要留夠足夠的擴展空間,不然,你日后來干這個事,你會死的很難看,參看Slashdot 的例子?(2009年11月06日),一個簡單的ALTER TABLE語句花了3個多小時,因為里面有一千六百萬條數據。

19. 選擇正確的存儲引擎

在 MySQL 中有兩個存儲引擎 MyISAM 和 InnoDB,每個引擎都有利有弊。以前文章《MySQL: InnoDB 還是 MyISAM??》討論和這個事情。

MyISAM 適合于一些需要大量查詢的應用,但其對于有大量寫操作并不是很好。甚至你只是需要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都 無法操作直到讀操作完成。另外,MyISAM 對于 SELECT COUNT(*) 這類的計算是超快無比的。

InnoDB 的趨勢會是一個非常復雜的存儲引擎,對于一些小的應用,它會比 MyISAM 還慢。他是它支持“行鎖” ,于是在寫操作比較多的時候,會更優秀。并且,他還支持更多的高級應用,比如:事務。

下面是MySQL的手冊

  • target=”_blank”MyISAM Storage Engine
  • InnoDB Storage Engine

20. 使用一個對象關系映射器(Object Relational Mapper)

使用 ORM (Object Relational Mapper),你能夠獲得可靠的性能增漲。一個ORM可以做的所有事情,也能被手動的編寫出來。但是,這需要一個高級專家。

ORM 的最重要的是“Lazy Loading”,也就是說,只有在需要的去取值的時候才會去真正的去做。但你也需要小心這種機制的副作用,因為這很有可能會因為要去創建很多很多小的查 詢反而會降低性能。

ORM 還可以把你的SQL語句打包成一個事務,這會比單獨執行他們快得多得多。

目前,個人最喜歡的PHP的ORM是:Doctrine?。

21. 小心“永久鏈接”

“永久鏈接”的目的是用來減少重新創建MySQL鏈接的次數。當一個鏈接被創建了,它會永遠處在連接的狀態,就算是數據庫操作已經結束了。而且,自 從我們的Apache開始重用它的子進程后——也就是說,下一次的HTTP請求會重用Apache的子進程,并重用相同的 MySQL 鏈接。

  • PHP 手冊:mysql_pconnect()

在理論上來說,這聽起來非常的不錯。但是從個人經驗(也是大多數人的)上來說,這個功能制造出來的麻煩事更多。因為,你只有有限的鏈接數,內存問 題,文件句柄數,等等。

而且,Apache 運行在極端并行的環境中,會創建很多很多的了進程。這就是為什么這種“永久鏈接”的機制工作地不好的原因。在你決定要使用“永久鏈接”之前,你需要好好地 考慮一下你的整個系統的架構。

阿里巴巴JAVA編程規范之MySQL規范

(一)?建表規約

1.?【強制】表達是與否概念的字段,必須使用is_xxx的方式命名,數據類型是unsigned tinyint。(?1表示是,0表示否),此規則同樣適用于odps建表。

說明:任何字段如果為非負數,必須是unsigned。

解讀:從優化角度來講,應該按字段的用途來定義合適的類型。表達是與否,用長度為1個字節的tinyint足以

2.?【強制】表名、字段名必須使用小寫字母或數字;禁止出現數字開頭,禁止兩個下劃線中間只出現數字。數據庫字段名的修改代價很大,因為無法進行預發布,所以字段名稱需要慎重考慮。

正例:getter_admin,task_config,level3_name

反例:GetterAdmin,taskConfig,level_3_name

說明:MySQL 在 Windows 下不區分大小寫,但在 Linux 下默認是區分大小寫。因此,數據庫名、 表名、字段名,都不允許出現任何大寫字母,避免節外生枝。

解讀:Win環境下開發,代碼中用的表名是小寫,本地數據庫用的是大寫,那么在win環境下沒有問題,但發布到linux環境會有問題。Linux下MySQL安裝完后默認:區分表名的大小寫,不區分列名的大小寫

3.?【強制】表名不使用復數名詞。

說明:表名應該僅僅表示表里面的實體內容,不應該表示實體數量,對應于DO類名也是單數形式,符合表達習慣。

4.?【強制】禁用保留字,如desc、range、match、delayed等,參考官方保留字。

5.?【強制】唯一索引名為uk_字段名;普通索引名則為idx_字段名。

說明:uk_即?unique key;idx_即index的簡稱。

6.?【強制】小數類型為decimal,禁止使用float和double。

說明:float和double在存儲的時候,存在精度損失的問題,很可能在值的比較時,得到不正確的結果。如果存儲的數據范圍超過decimal的范圍,建議將數據拆成整數和小數分開存儲。

解讀:float和double都是浮點型,而decimal是定點型。MySQL 浮點型和定點型可以用類型名稱后加(M,D)來表示,M表示該值的總共長度,D表示小數點后面的長度。FLOAT和DOUBLE在不指定精度時,默認會按照實際的精度來顯示,而DECIMAL在不指定精度時,默認整數為10,小數為0。所以建議在定義表時,定義(M,D)。float和double在設置超過定義長度的數值時,會自動四舍五入,decimal會截斷,并給出一條警告。精度損失問題:float和double類型的列,在做sum計算時,會丟失精度,而decimal會精確計算。

7.?【強制】如果存儲的字符串長度幾乎相等,使用CHAR定長字符串類型。

解讀:從優化角度來說,如果一個表的所有字段都是定長的,那么每一條數據也就是定長的,數據庫就可以直接計算出下一條數據的偏移量,查詢速度會更快。

8.?【強制】varchar是可變長字符串,不預先分配存儲空間,長度不要超過5000,如果存儲長度大于此值,定義字段類型為TEXT,獨立出來一張表,用主鍵來對應,避免影響其它字段索引效率。

解讀:MySQL5.0以上版本,varchar最大可以存儲65535字節數據(內容開頭用1-2個字節存儲長度信息,超過255時用兩個字節,所以最大65535)。我們通常編碼設置為U8,每個字符最多占3個字節,那么最大長度不能超過21845。若定義的時候超過上述限制,則varchar字段會被強行轉為text類型,并產生warning。此外,受MYSQL行長度限制影響,MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示ERROR 1118 (42000): Row size too large。數據庫中定義的varchar(20)指的是20個字符。關于5000的建議:由于通常定義的U8每個字符占3個字節,那么5000字符需要15000個字節,考慮行最大長度限制和別的列,以及查詢性能,推薦5000。

9.?【強制】表必備三字段:id, gmt_create, gmt_modified。

說明:其中id必為主鍵,類型為unsigned bigint、單表時自增、步長為1;分表時改為從TDDL?Sequence取值,確保分表之間的全局唯一。gmt_create,gmt_modified的類型均為date_time類型。

10.【推薦】表的命名最好是加上“業務名稱_表的作用”,避免上云梯后,再與其它業務表關聯時有混淆。

正例:tiger_task / tiger_reader / mpp_config

11.【推薦】庫名與應用名稱盡量一致。

12.【推薦】如果修改字段含義或對字段表示的狀態追加時,需要及時更新字段注釋。

13.【推薦】字段允許適當冗余,以提高性能,但是必須考慮數據同步的情況。冗余字段應遵循:

  • 不是頻繁修改的字段。
  • 不是varchar超長字段,更不能是text字段。

正例:各業務線經常冗余存儲商品名稱,避免查詢時需要調用IC服務獲取。商品類目名稱使用頻率高,字段長度短,名稱基本一成不變,可在相關聯的表中冗余存儲類目名稱,避免關聯查詢。

14.【推薦】單表行數超過500萬行或者單表容量超過2GB,才推薦進行分庫分表。

說明:如果預計三年后的數據量根本達不到這個級別,請不要在創建表時就分庫分表。

反例:某業務三年總數據量才2萬行,卻分成1024張表,問:你為什么這么設計?答:分1024張表,不是標配嗎?

15.【參考】合適的字符存儲長度,不但節約數據庫表空間、節約索引存儲,更重要的是提升檢索速度。

正例:人的年齡用unsigned tinyint(表示范圍0-255,人的壽命不會超過255歲);海龜就必須是small int,但如果是太陽的年齡,就必須是int;如果是所有恒星的年齡都加起來,那么就必須使用bigint。

(二)?索引規約

1.?【強制】業務上具有唯一特性的字段,即使是組合字段,也必須建成唯一索引。

說明:不要以為唯一索引影響了insert速度,這個速度損耗可以忽略,但提高查找速度是明顯的;另外,即使在應用層做了非常完善的校驗和控制,只要沒有唯一索引,根據墨菲定律,必然有臟數據產生。

2.?【強制】超過三個表禁止join。需要join的字段,數據類型保持絕對一致;多表關聯查詢時,保證被關聯的字段需要有索引。

說明:即使雙表join也要注意表索引、SQL性能。

3.?【強制】在varchar字段上建立索引時,必須指定索引長度,沒必要對全字段建立索引,根據實際文本區分度決定索引長度。

說明:索引的長度與區分度是一對矛盾體,一般對字符串類型數據,長度為20的索引,區分度會高達90%以上,可以使用count(distinct left(列名,索引長度))/count(*)的區分度來確定。

解讀:區分度是指不重復的索引值和數據表的記錄總數的比值,范圍(0,1],值越高則查詢效率越高。對于blob,text,varchar的列必須使用前綴索引,MySQL不允許索引這些列的完整長度。最好選擇足夠長的前綴保證較高的區分度,也不能太長(節省空間)。

4.?【強制】頁面搜索嚴禁左模糊或者全模糊,如果需要請走搜索引擎來解決。

說明:索引文件具有B-Tree的最左前綴匹配特性,如果左邊的值未確定,那么無法使用此索引。

5.?【推薦】如果有order?by的場景,請注意利用索引的有序性。order?by?最后的字段是組合索引的一部分,并且放在索引組合順序的最后,避免出現file_sort的情況,影響查詢性能。

正例:where a=? and b=? order by c;?索引:a_b_c

反例:索引中有范圍查找,那么索引有序性無法利用,如:WHERE?a>10?ORDER?BY?b;?索引a_b無法排序。

解讀:只有在order by 數據列的時候才可能會出現using filesort,而且如果你不對進行order by的這一列設置索引的話,無論列值是否有相同的都會出現using filesort。因此,只要用到order by 的這一列都應該為其建立一個索引。 只有當索引的列順序和order by子句的順序完全一致,并且所有列的排序方向都一樣時,才能用索引排序。如果查詢需要關聯多張表,只有當order by子句引用的字段全部為第一個表時,才能使用索引排序。

6.?【推薦】利用覆蓋索引來進行查詢操作,來避免回表操作。

說明:如果一本書需要知道第11章是什么標題,會翻開第11章對應的那一頁嗎?目錄瀏覽一下就好,這個目錄就是起到覆蓋索引的作用。

正例:IDB能夠建立索引的種類:主鍵索引、唯一索引、普通索引,而覆蓋索引是一種查詢的一種效果,用explain的結果,extra列會出現:using index.

解讀:如果一個索引包含所有需要查詢的字段的值,稱之為“覆蓋索引”。由于覆蓋索引必須要存儲索引列的值,哈希索引、空間索引和全文索引都不存儲列的值,MySQL只有B-Tree索引可以做覆蓋索引。如:對id,name,title三個字段建立索引,在索引中會存儲這三個列的值,如果查詢:select id,name,title from table where id < 10; 通過explain會看到extra為using index。如果查詢select * from table where id < 10;就不會使用覆蓋索引,因為索引中沒有包含所有的列值。

7.?【推薦】利用延遲關聯或者子查詢優化超多分頁場景。

說明:MySQL并不是跳過offset行,而是取offset+N行,然后返回放棄前offset行,返回N行,那當offset特別大的時候,效率就非常的低下,要么控制返回的總頁數,要么對超過特定閾值的頁數進行SQL改寫。

解讀:案例

select count(*) from user_game_info; // 共有956176條數據

select * from user_game_info a limit 900000, 20; // 此查詢耗時0.547S

優化前

?

select t1.* from user_game_info t1, (select id from user_game_info limit 900000, 20) t2 where t1.id = t2.id; // 優化后耗時0.178S

優化后

8.?【推薦】SQL性能優化的目標:至少要達到?range級別,要求是ref級別,如果可以是consts最好。

? 說明:

  • consts單表中最多只有一個匹配行(主鍵或者唯一索引),在優化階段即可讀取到數據。
  • ref指的是使用普通的索引。(normal index)
  • range對索引進范圍檢索。

反例:explain表的結果,type=index,索引物理文件全掃描速度非常慢,這個index級別比較range還低,與全表掃描是小巫見大巫。

9.?【推薦】建組合索引的時候,區分度最高的在最左邊。

正例:如果where a=? and b=??,a列的幾乎接近于唯一值,那么只需要單建idx_a索引即可。

說明:存在非等號和等號混合判斷條件時,在建索引時,請把等號條件的列前置。如:wherea>? and b=??那么即使a的區分度更高,也必須把b放在索引的最前列。

10.【推薦】 防止因字段類型不同造成的隱式轉換,導致索引失效。

解讀:例如,給上文提到的tb_user_account表的username(varchar)字段加索引,由于字段是varchar類型的,所以上圖中的查詢類型匹配,命中索引,下圖是用int類型匹配的,無法命中索引。

以字符串形式查找,命中索引

字符串命中索引

?

因隱式轉換,未命中索引

數值未命中索引

?

隱式轉換規則:

  • 兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 做比較時會返回 1,這兩種情況都不需要做類型轉換
  • 兩個參數都是字符串,會按照字符串來比較,不做類型轉換
  • 兩個參數都是整數,按照整數來比較,不做類型轉換
  • 十六進制的值和非數字做比較時,會被當做二進制串
  • 有一個參數是 TIMESTAMP 或 DATETIME,并且另外一個參數是常量,常量會被轉換為 timestamp
  • 有一個參數是 decimal 類型,如果另外一個參數是 decimal 或者整數,會將整數轉換為 decimal 后進行比較,如果另外一個參數是浮點數,則會把 decimal 轉換為浮點數進行比較
  • 所有其他情況下,兩個參數都會被轉換為浮點數再進行比較

11.【參考】創建索引時避免有如下極端誤解:

  • 誤認為一個查詢就需要建一個索引。
  • 誤認為索引會消耗空間、嚴重拖慢更新和新增速度。
  • 誤認為唯一索引一律需要在應用層通過“先查后插”方式解決。

(三)?SQL規約

1.?【強制】不要使用count(列名)或count(常量)來替代count(*),count(*)就是SQL92定義的標準統計行數的語法,跟數據庫無關,跟NULL和非NULL無關。

說明:count(*)會統計值為NULL的行,而count(列名)不會統計此列為NULL值的行。

2.?【強制】count(distinct col)?計算該列除NULL之外的不重復數量。注意?count(distinct col1, col2)?如果其中一列全為NULL,那么即使另一列有不同的值,也返回為0。

3.?【強制】當某一列的值全是NULL時,count(col)的返回結果為0,但sum(col)的返回結果為 NULL,因此使用sum()時需注意NPE問題。

正例:可以使用如下方式來避免sum的NPE問題:SELECTIF(ISNULL(SUM(g)),0,SUM(g))FROM table;

4.?【強制】使用ISNULL()來判斷是否為NULL值。注意:NULL與任何值的直接比較都為NULL。

? 說明:

  • NULL<>NULL的返回結果是NULL,不是false。
  • NULL=NULL的返回結果是NULL,不是true。
  • NULL<>1的返回結果是NULL,而不是true。

5.?【強制】在代碼中寫分頁查詢邏輯時,若count為0應直接返回,避免執行后面的分頁語句。

6.?【強制】不得使用外鍵與級聯,一切外鍵概念必須在應用層解決。

說明:(概念解釋)學生表中的student_id是主鍵,那么成績表中的student_id則為外鍵。如果更新學生表中的student_id,同時觸發成績表中的student_id更新,則為級聯更新。外鍵與級聯更新適用于單機低并發,不適合分布式、高并發集群;級聯更新是強阻塞,存在數據庫更新風暴的風險;外鍵影響數據庫的插入速度。

7.?【強制】禁止使用存儲過程,存儲過程難以調試和擴展,更沒有移植性。

8.?【強制】IDB數據訂正時,刪除和修改記錄時,要先select,避免出現誤刪除,確認無誤才能提交執行。

9.?【推薦】in操作能避免則避免,若實在避免不了,需要仔細評估in后邊的集合元素數量,控制在1000個之內。

10.【參考】因阿里巴巴全球化需要,所有的字符存儲與表示,均以utf-8編碼,那么字符計數方法注意:

說明:

SELECT LENGTH("阿里巴巴");?返回為12

SELECT CHARACTER_LENGTH("阿里巴巴");?返回為4

如果要使用表情,那么使用utfmb4來進行存儲,注意它與utf-8編碼。

11.【參考】TRUNCATE?TABLE?比?DELETE速度快,且使用的系統和事務日志資源少,但TRUNCATE無事務且不觸發trigger,有可能造成事故,故不建議在開發代碼中使用此語句。

說明:TRUNCATE TABLE?在功能上與不帶?WHERE子句的?DELETE語句相同。

(四)?ORM規約

1.?【強制】在表查詢中,一律不要使用?*作為查詢的字段列表,需要哪些字段必須明確寫明。

說明:1)增加查詢分析器解析成本。2)增減字段容易與resultMap配置不一致。3)無用字段增加網絡消耗,尤其是 text 類型的字段。

2.?【強制】POJO類的boolean屬性不能加is,而數據庫字段必須加is_,要求在resultMap中進行字段與屬性之間的映射。

說明:參見定義POJO類以及數據庫字段定義規定,在sql.xml增加映射,是必須的。

3.?【強制】不要用resultClass當返回參數,即使所有類屬性名與數據庫字段一一對應,也需要定義;反過來,每一個表也必然有一個與之對應。

說明:配置映射關系,使字段與DO類解耦,方便維護。

4.?【強制】xml配置中參數注意使用:#{},#param#不要使用${}此種方式容易出現SQL注入。

解讀:#與$的區別:在預編譯中的處理是不一樣的。#{} 在預處理時,會把參數部分用一個占位符 ? 代替,如:select * from user where name = ?;而 ${} 則只是簡單的字符串替換,在動態解析階段,該 sql 語句會被解析成select * from user where name = 'zhangsan’;以上,#{} 的參數替換是發生在 DBMS 中,而 ${} 則發生在動態解析過程中。

5.?【強制】iBATIS自帶的queryForList(String?statementName,int?start,int?size)不推薦使用。

說明:其實現方式是在數據庫取到statementName對應的SQL語句的所有記錄,再通過subList取start,size的子集合,線上因為這個原因曾經出現過OOM。

正例:在sqlmap.xml中引入?#start#, #size#

Map<String, Object> map = new HashMap<String,Object>();

map.put("start", start);

map.put("size", size);

6.?【強制】不允許直接拿HashMap與HashTable作為查詢結果集的輸出。

反例:某同學為避免寫一個<resultMap>,直接使用HashTable來接收數據庫返回結果,結果出現日常是把bigint轉成Long值,而線上由于數據庫版本不一樣,解析成BigInteger,導致線上問題。

7.?【強制】更新數據表記錄時,必須同時更新記錄對應的gmt_modified字段值為當前時間。

8.?【推薦】不要寫一個大而全的數據更新接口,傳入為POJO類,不管是不是自己的目標更新字段,都進行update?table?set?c1=value1,c2=value2,c3=value3;?這是不對的。執行SQL時,盡量不要更新無改動的字段,一是易出錯;二是效率低;三是binlog增加存儲。

9.?【參考】@Transactional事務不要濫用。事務會影響數據庫的QPS,另外使用事務的地方需要考慮各方面的回滾方案,包括緩存回滾、搜索引擎回滾、消息補償、統計修正等。

10.【參考】<isEqual>中的compareValue是與屬性值對比的常量,一般是數字,表示相等時帶上此條件;<isNotEmpty>表示不為空且不為null時執行;<isNotNull>表示不為null值時執行。

阿里十年java老兵總結的50條mysql使用軍規

一.數據庫配置
????????1. innodb_flush_log_at_trx_commit,這個對支付業務來說是關鍵性的設置之一,可選的參數值有0,1,2, 支付需要設置成1.

????????2. 對交易以及記賬部分來說,必須是innode引擎,以支持事務

????????3. 事務隔離級別,權衡安全性和效率,使用可重復讀

????????4. innodb_lock_wait_timeout,這個是鎖超時時間,不建議太大,怕引起雪崩

二.業務設計
????1. 不用物理刪除,即盡量避免用delete語句,drop命令等;通過軟刪除處理,即通過額外的字段標

????2. 明記錄的刪除狀態;雖然對寫代碼來講有些麻煩,但實踐證明是非常值得的

????3. 在系統設計之初就要定好編碼規范,對存入的數據做相應轉換并做好escape處理

????4. 除列表查詢外,盡量用主鍵操作;核心交易系統中盡量避免非主鍵操作

????5. 避免schema中1對多設計,概念簡單,編碼很難

????6. 就mysql來說,盡量使用其最簡單的功能,不用其高級功能如觸發器,連表等

????7. 就mysql來說,盡量不讓其做計算功能,而是讓業務層來實現計算邏輯

????8. 當要鎖多條記錄時, 要考慮死鎖的可能以及預防的措施

????9. 按業務垂直劃分原則,盡量把不同的業務方不同的庫中

????10. 堅持小事務,一個大事務與將其拆分成的十個小事務相比,小事務對數據庫壓力更小;另外,事務

中做盡可能少的事情,神馬參數校驗之類的事情能拉出去就拉出去

????11. 數據庫連接長時間不用超時斷開是常見的,應用中需要考慮

????12. 對超大型系統來說,分布式事務是有價值的;但在大多下情況下,單機事務能很好的滿足需要

????13. 主從延遲總是會有的,有時候會很大,設計中要考慮

????14. 讀寫賬號分開,讀賬號select權限即可,寫賬號update,insert即可

????15. where條件key='value'的模式中,加上單引號總是對的,不加在某些情況下有很多令人意外的副

作用

????16. 盡量使用簡單的數據類型,char系列,int系列以及date系列即可

????17. 事務的使用上,在線交易使用悲觀鎖

????18. 事務框架的選擇上,使用控制力度比較大的,直接TransactionManager,不推薦使用聲明式事務

????19. 采用InnoDB引擎,UTF8編碼

????20. 有狀態字段的記錄,狀態的取值不宜太多, 6 ~ 7個應該是上限了, 最好不要超過 4個

????21. 每個表都應該有自己的主鍵,且盡量讓表內主鍵保持遞增

????22. 不使用自增主鍵

????23. 在線查詢的字段一定要建立覆蓋索引

????24. 分頁查找一定不能直接limit m,n,一定要做優化

三. 應用規范
????1. 當進行賬戶余額變化操作時,總是校驗賬戶是否被凍

????2. 對單據如Trade,Charge進行處理,并發總是要考慮的,需要鎖記錄后進行校驗;從數據庫查詢的

時候,請先起動事務,并用select...for update;防止并發帶來的問題;從性能上將,鎖交易單本身不

會成為性能瓶頸

????3. 更新賬戶余額之前必須加鎖,即起事務+select...for update; 更新余額的語句建議是update table

set 余額=余額+/-發生額, 自然在代碼邏輯中做各種邊界值校驗,包括不溢出,不小于0等

????4.金額都統一單位,以分為單位合適;數據類型為有符號64位整形數合適

????5. 對金額計算時,對溢出的預防總是需要的

????6.使用select時,慎用*,盡量明確的枚舉出字段名

????7.與外部交互的地方,記錄下外部發生時間

????8. db命名采用"cashpay"前綴

????9. 表命名采用"t_"前綴

????10. 字段命名采用"F_"前綴

????11. 每個表都會有一個字段記錄上次更新時間

????12. 在一個session中的所有數據庫更新記錄,上次更新時間都是一致的

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454652.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454652.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454652.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

hadoop-09-安裝資源上傳

hadoop-09-安裝資源上傳 在/software/www/html 下面上傳 ambari HDP HDP-UTILS-1.1.0.21 文件&#xff0c;之后解壓&#xff1b;

easyui 收費_收費班長喻玉華三尺崗亭獻青春

- 2020 第四期 人物訪談報道 -拼搏人生最美勵志先鋒人物專訪2013年&#xff0c;22歲的她來到巴南高速這個大家庭中&#xff0c;成為恩陽收費站一名普通的收費員。懷著對事業的執著追求與熱愛&#xff0c;經過兩年不懈的努力&#xff0c;獲得了領導和同事的認可和喜愛。2015年5月…

編程技術面試的五大要點

&#xff08;寫在前面的話&#xff1a;本文最初發表于《程序員》雜志2011年10月刊&#xff0c;并收錄到《劍指Offer——名企面試官精講典型編程題》一書中。&#xff09; 近年來找工作一直是一個很熱門的話題。我們要想找到心儀的工作&#xff0c;難免需要經過很多輪面試。編程…

訪問linux服務主機,如何把Linux配置為日志服務主機。

如網絡設備很多&#xff0c;可把同類的設備配置為相同的設備號例&#xff1a;more switch.log | grep X.X.X.X //查看某一設備的日志審核和記錄系統的事件是非常重要的。如果僅僅把系統事件作為日志記錄下來&#xff0c;而不去查看&#xff0c;還是無濟于事。可用webadmin管理和…

WSARecv() 函數使用解析

詳情參考&#xff1a;https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(vvs.85).aspx 簡述 The WSARecv function receives data from a connected socket or a bound connectionless socket. The WSARecv function provides some additional features comp…

獲取 docker 容器(container)的 ip 地址

獲取單個IP docker inspect --format {{ .NetworkSettings.IPAddress }} <container-ID> 獲取所有容器IP docker inspect -f {{.Name}} - {{.NetworkSettings.IPAddress }} $(docker ps -aq)轉載于:https://www.cnblogs.com/Tempted/p/7774789.html

山西臺達plc可編程控制器_可編程控制器2(PLC)控制原理

采用繼電器控制采用PC控制PC的控制原理(繼電器PC控制)a)當SB1按下&#xff0c;輸入繼電器00000的線圈通電&#xff0c;00000的常開觸點閉合&#xff0c;使得輸出繼電器01000的線圈得電&#xff0c;01000對應的硬輸出觸電閉合&#xff0c;KM1得電M1開始運轉&#xff0c;同時0100…

一篇讀懂 可轉債

可轉債興起的原因 可轉債是1992年底開始進入中國證券市場的&#xff0c;到現在已經27個年頭了。可以說&#xff0c;以前可轉債在中國證券市場一直不是市場的焦點和幸運兒&#xff0c;始終沒能成為一個上規模的可配置的投資品種——其原因很簡單&#xff0c;因為相對而言企業發…

bodhi linux 安裝 ubuntu軟件,Bodhi Linux 5.1.0 發布,基于Ubuntu的輕量級發行版

Bodhi Linux是基于Ubuntu的輕量級發行版&#xff0c;具有Moksha桌面環境。現在有很多Linux發行版。有些是獨特的&#xff0c;但很多是重復的&#xff0c;可能沒有存在的必要。由于使用了Moksha桌面環境&#xff0c;一個基于Linux的操作系統Bodhi脫穎而出。如果你不熟悉Bodhi&am…

談一談周公所理解的面試

因為公司最近招聘的力度很大&#xff0c;所以最近公司的面試很多&#xff0c;加之很多同事項目緊&#xff0c;所以讓我參加了一些技術面試。不論是作為面試官還是應聘者&#xff0c;參加工作以來我參與的面試的次數我自己也記不清了&#xff0c;所以在此想從面試官和應聘者的角…

idc機房運維巡檢_智和信通賦能國產信創 建設IT智能監控運維體系 - 蔚穎willing...

作為信創領域深耕多年的企業&#xff0c;北京智和信通技術有限公司始終堅持研發自主知識產權的IT智能運維監控大數據分析系統——智和網管平臺SugarNMS&#xff0c;積極探索AIOps智能運維&#xff0c;通過“國產安全監控分析安管日志運維開發”七合一模式&#xff0c;賦能IDC數…

long long or int

long long or int 很多時候long long爆空間&#xff0c;int有時又不夠 。 在算乘法的時候&#xff0c;要保證乘出來的中間項也不爆long long 轉載于:https://www.cnblogs.com/war1111/p/7532412.html

用Python的Tultle模塊創建一個五角星

方案所需準備Python官方手冊。 這里是我找到的中文版。一個可執行Python的解釋器Ttultle簡介來源烏龜圖形是一個不錯的方式來為孩子們介紹編程。它是Wally Feurzig和Seymour Papert在1966年開發的原始Logo編程語言的一部分。想象一只在x-y平面上&#xff0c;從&#xff08;0,0&…

鏡像上傳到linux失敗,Docker push鏡像失敗解決方法

Docker push鏡像失敗解決方法發布時間&#xff1a;2017-03-09 12:07來源&#xff1a;互聯網當前欄目&#xff1a;web技術類Docker push鏡像失敗的問題。以下是輸入push自己的tomcat后出現了失敗[rootslave3 ~]# docker push lekkoliu/tomcat8:latestThe push refers to a repos…

Python 之 Python2 和 Python3 的區別

1、默認編碼方式 # Python2 默認編碼方式是 ascll碼 # Python3 默認編碼方式是 utf-8 # Python2 輸出中文要加 # -*- encoding:utf-8 -*- # Python3 不需要 2、print # Python2 可以使用 print&#xff0c;也可以使用 print() 例&#xff1a; print(lili) 或 print lili # Py…

【C/C++開發】C++11 并發指南二(std::thread 詳解)

上一篇博客《C11 并發指南一(C11 多線程初探)》中只是提到了 std::thread 的基本用法&#xff0c;并給出了一個最簡單的例子&#xff0c;本文將稍微詳細地介紹 std::thread 的用法。 std::thread 在 <thread> 頭文件中聲明&#xff0c;因此使用 std::thread 時需要包含 &…

【找工作資料】外企面試技巧

這里談談面試的技巧。這是根據誠迅聯豐咨詢公司許國慶在北大光華管理學院、經濟學院和清華經濟管理學院的講座整理出來的。他曾在美國的投資銀行和商業銀行工作了近十年。 一、面試前的準備 1&#xff0e;確定3W 明確面試前的三要素&#xff0d;When (時間)、Where&#xf…

觸摸屏Sensor疊構實例學習記錄(一)

現在從事TP這個行業&#xff0c;看再多的資料和介紹&#xff0c;不如直接拿個實例的工程圖來看&#xff0c;分析每一部分具體是什么東西&#xff0c;比看再多的資料更容易入門。 以下圖紙和圖片都是我從網上隨便下的&#xff0c;僅次于學習記錄使用&#xff0c;不做另外的商業用…

linux查找influx的安裝位置,InfluxDB學習之InfluxDB的安裝和簡介 | Linux大學

最近用到了 InfluxDB&#xff0c;在此記錄下學習過程&#xff0c;同時也希望能夠幫助到其他學習的同學。本文主要介紹InfluxDB的功能特點以及influxDB的安裝過程。更多InfluxDB詳細教程請看&#xff1a;InfluxDB系列學習教程目錄一、InfluxDB 簡介InfluxDB 是用Go語言編寫的一個…

Python 之數據類型

文章收集于網絡&#xff0c;如有版權&#xff0c;請聯系作者 一、引子 1 什么是數據&#xff1f; x10&#xff0c;10是我們要存儲的數據 2 為何數據要分不同的類型 數據是用來表示狀態的&#xff0c;不同的狀態就應該用不同的類型的數據去表示 3 數據類型 數字、字符串、列表…