20191127 數據庫查詢優化方案

不能跨庫查詢是一種理念,每個庫所有的數據出口、入口,只能有一箇中間件,要統一收口,要不然不能確定數據從哪裏落庫的,從哪裏出去的。

 

-- 不爲null這個條件經常忘記
select pd.id,ai.id from p_doctor pd  
inner join account_info ai
on ai.id=pd.acct_id
where pd.register_source!=ai.register_source 
and pd.register_source=0 
and ai.register_source!=0 
and ai.register_source is not null;  

 

每個微服務只能訪問自己的表,每個微服務的表存放在一個單獨的數據庫中(大公司都這樣)。

分庫後如果想刷數據,只能進行數據的導入導出。

 

使用事務進行管理

1、把數據插入本地account_info;

2、遠程調用寫入到一個事務方法裏面。

 

mysql時間類型比較。

SELECT * FROM p_hospital where modify_time > '2019-12-20 00:00:00' and modify_time < '2019-12-20 11:00:00' (datetime類型)

SELECT * FROM p_doctor where modify_time > '2019-12-19 20:00:00' and modify_time < '2019-12-20 11:00:00'

 

寫查詢語句的時候 單詞拼寫錯誤,導致查詢報錯(一般都是拼寫錯誤)。 primary("id") 通過sql語句創建表。 一定要在線下環境執行多次sql,避免在生產環境執行不了。 分號,庫名必須要帶。

 

delete與truncate的區別?

1)delete刪除的時候是一條一條的刪除記錄,它配合事務,可以將刪除的數據找回。

2)truncate刪除,它是將整個表摧毀(會重置auto_increment),然後再創建一張一模一樣的表。它刪除的數據無法找回。

 

日誌表

就算大於500萬條記錄,也不用拆表,因爲日誌表如果數據滿了,就不會在寫入數據,只用來保存數據,直接切換到新的數據表即可。

 

每天創建一張表:通過代碼創建,mybatis支持。

mysql複製表結構和數據,什麼情況下需要複製表結構和數據?

比如日誌表需要複製表結構和數據。

 

select * from 表名 procedure analyse();

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

最後一列爲建議列。

 

explain:執行計劃中的執行概況;分析當前sql執行過程中的資源消耗情況。

哪些操作耗時最大? 執行"概況"

 

 

1.使用索引

 

應儘量避免全表掃描,首先應考慮在 where 及 order by ,group by 涉及的列上建立索引。

 

2.優化 SQL 語句

2.1通過 explain(查詢優化神器)用來查看 SQL 語句的執行效果(查看sql執行計劃,選擇最優路徑)

可以幫助選擇更好的索引和優化查詢語句, 寫出更好的優化語句。 通常我們可以對比較複雜的尤其是涉及到多表的 SELECT 語句, 把關鍵字 EXPLAIN 加到前面, 查看執行計劃。

例如: explain select * from news;

2.2任何地方都不要使用 select * from t;

用具體的字段列表代替“*” , 不要返回用不到的任何字段。

mysql innodb上的理解。

1),不需要的字段會增加數據傳輸的時間,即使mysql服務器和客戶端是在同一臺機器上,使用的協議還是tcp,通信也是需要額外的時間。

2),要取的字段、索引的類型,和這兩個也是有關係的。舉個例子,對於user表,有name和phone的聯合索引,select name from user where phone=12345678912 和 select * from user where phone=12345678912,前者要比後者的速度快,因爲name可以在索引上直接拿到,不再需要讀取這條記錄了(是否需要回表查詢)。

3),大字段,例如很長的varchar,blob,text。準確來說,長度超過728字節的時候,會把超出的數據放到另外一個地方,因此讀取這條記錄會增加一次io操作。

2.3索引列不能參與計算,保持列“乾淨”

比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’);(列上不能進行計算,否則會導致索引失效)

2.4查詢儘可能使用 limit 減少返回的行數, 減少數據傳輸時間和帶寬浪費。

 

3 優化數據庫對象

3.1優化表的數據類型

使用 procedure analyse()函數對錶進行分析,該函數可以對錶中列的數據類型提出優化建議。 能小就用小。 表數據類型第一個原則是: 使用能正確的表示和存儲數據的最短類型。 這樣可以減少對磁盤空間、 內存、 cpu 緩存的使用。

使用方法: select * from 表名 procedure analyse();

3.2 對錶進行拆分

通過拆分表可以提高表的訪問效率。 有 2 種拆分方法1.垂直拆分。把主鍵和一些列放在一個表中, 然後把主鍵和另外的列放在另一個表中。 如果一個表中某些列常用, 而另外一些不常用, 則可以採用垂直拆分。2.水平拆分。根據一列或者多列數據的值把數據行放到二個獨立的表中。

3.3 使用中間表來提高查詢速度

創建中間表, 表結構和源表結構完全相同, 轉移要統計的數據到中間表, 然後在中間表上進行統計, 得出想要的結果。

 

4.硬件優化

4.1 CPU 的優化

選擇多核和主頻高的 CPU。

4.2 內存的優化

使用更大的內存。 將盡量多的內存分配給 MYSQL 做緩存。

4.3 磁盤 I/O 的優化

4.3.1 使用磁盤陣列

RAID 0 沒有數據冗餘, 沒有數據校驗的磁盤陳列。 實現 RAID 0至少需要兩塊以上的硬盤, 它將兩塊以上的硬盤合併成一塊, 數據連續地分割在每塊盤上。

RAID1 是將一個兩塊硬盤所構成 RAID 磁盤陣列, 其容量僅等於一塊硬盤的容量, 因爲另一塊只是當作數據“鏡像”。使用 RAID-0+1 磁盤陣列。 RAID 0+1 是 RAID 0 和 RAID 1 的組合形式。 它在提供與 RAID 1 一樣的數據安全保障的同時, 也提供了與 RAID 0 近似的存儲性能。

4.3.2 調整磁盤調度算法

選擇合適的磁盤調度算法, 可以減少磁盤的尋道時間

 

5.MySQL 自身的優化(配置文件)

對 MySQL 自身的優化主要是對其配置文件 my.cnf 中的各項參數進行優化調整。 如指定 MySQL 查詢緩衝區的大小, 指定 MySQL 允許的最大連接進程數等。

 

6.應用優化

6.1 使用數據庫連接池

6.2 使用查詢緩存

它的作用是存儲 select 查詢的文本及其相應結果。 如果隨後收到一個相同的查詢, 服務器會從查詢緩存中直接得到查詢結果。 查詢緩存適用的對象是更新不頻繁的表, 當表中數據更改後, 查詢緩存中的相關條目就會被清空。

 

數據庫sql常見優化方案

爲什麼要優化:隨着實際項目的啓動,數據庫經過一段時間的運行,最初的數據庫設置,會與實際數據庫運行性能會有一些差異,這時我們就需要做一個優化調整。

(主機性能,內存使用性能,網絡傳輸性能,架構方面,sql語句執行性能等)

1、SELECT子句中避免使用*號

數據庫在解析的過程中,會將*依次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味着將耗費更多的時間。

2、數據庫採用自右而左的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之左, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的之右(笛卡爾積的數量變少了)。

on...where...and... 連接查詢,笛卡爾積。WHERE子句中的連接順序。

3、選擇最有效率的表名順序,數據庫的解析器按照從右到左的順序處理FROM子句中的表名,

FROM子句中寫在最後的表將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表放在最後,如果有3個以上的表連接查詢,那就需要選擇那個被其他表所引用的表放在最後。

1)如果三個表是完全無關係的話,將記錄和列名最少的表,寫在最後,然後依次類推;

2)如果三個表是有關係的話,將引用最多的表,放在最後,然後依次類推;

記錄少需要的時間比較短。連接查詢會生成臨時表。

注意:From子句中表的順序。

4、明知只有一條查詢結果,那請使用 “LIMIT 1”。“LIMIT 1”可以避免全表掃描,找到對應結果就不會再繼續掃描了。

5、爲列選擇合適的數據類型

能用TINYINT就不用SMALLINT,能用SMALLINT就不用INT,道理你懂的,磁盤和內存消耗越小越好嘛。

6、SQL UNION 操作符:UNION 操作符用於合併兩個或多個 SELECT 語句的結果集。UNION 內部的 SELECT 語句必須擁有相同數量的列。列也必須擁有相似的數據類型。同時,每條 SELECT 語句中的列的順序必須相同。聯合查詢

使用UNION ALL 代替 UNION,如果結果集允許重複的話。因爲 UNION ALL 不去重,效率高於 UNION。

7、爲獲得相同結果集的多次執行,請保持SQL語句前後一致;這樣做的目的是爲了充分利用查詢緩存。

比如根據地域和產品id查詢產品價格,第一次使用了:那麼第二次同樣的查詢,請保持以上語句的一致性,比如不要將where語句裏面的id和region位置調換順序。

緩存條件:查詢緩存可以看做是SQL文本和查詢結果的映射。如果第二次查詢的SQL和第一次查詢的SQL完全相同(注意必須是完全相同,即使多一個空格或者大小寫不同都認爲不同)且開啓了查詢緩存,那麼第二次查詢就直接從查詢緩存中取結果。

8、WHERE 子句裏面的列儘量被索引

只是“儘量”哦,並不是說所有的列。因地制宜,根據實際情況進行調整,因爲有時索引太多也會降低性能(原因是什麼?)。

索引太多影響:某個表有100多個索引;插入或者修改數據表中的數據時,如果這一列建立了索引,那麼所有和此列相關的索引都會被更新,100多個索引的更細會導致修改特別慢。

更新比較少的字段,建立索引。

9、ORDER BY的列如果被索引,性能也會更好。

使用 LIMIT 實現分頁邏輯;不僅提高了性能,同時減少了不必要的數據庫和應用間的網絡傳輸。

使用 EXPLAIN 關鍵字去查看執行計劃:EXPLAIN 可以檢查索引使用情況以及掃描的行。

 

我們在使用Mysql數據庫是常見的兩個瓶頸是CPU和I/O的瓶頸,CPU在飽和的時候一般發生在數據裝入內存或從磁盤上讀取數據時候。磁盤I/O瓶頸的出現呢發生在裝入數據遠大於內存容量的時候,如果應用分佈在網絡上,那麼查詢量相當大的時候那麼平瓶頸就會出現在網絡上。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章