自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL之SQL優(yōu)化實戰(zhàn)記錄

數(shù)據(jù)庫 MySQL
本次SQL優(yōu)化是針對javaweb中的表格查詢做的。N個機臺將業(yè)務數(shù)據(jù)發(fā)送至服務器,服務器程序?qū)?shù)據(jù)入庫至MySQL數(shù)據(jù)庫。服務器中的javaweb程序?qū)?shù)據(jù)展示到網(wǎng)頁上供用戶查看。

背景

本次SQL優(yōu)化是針對javaweb中的表格查詢做的。

部分網(wǎng)絡架構(gòu)圖

 

MySQL之SQL優(yōu)化實戰(zhàn)記錄

 

業(yè)務簡單說明

N個機臺將業(yè)務數(shù)據(jù)發(fā)送至服務器,服務器程序?qū)?shù)據(jù)入庫至MySQL數(shù)據(jù)庫。服務器中的javaweb程序?qū)?shù)據(jù)展示到網(wǎng)頁上供用戶查看。

原數(shù)據(jù)庫設計

  • windows單機主從分離
  • 已分表分庫,按年分庫,按天分表
  • 每張表大概20w左右的數(shù)據(jù)

原查詢效率

3天數(shù)據(jù)查詢70-80s

目標

3-5s

業(yè)務缺陷

無法使用sql分頁,只能用java做分頁。

問題排查

前臺慢 or 后臺慢

  • 如果你配置了druid,可在druid頁面中直接查看sql執(zhí)行時間和uri請求時間
  • 在后臺代碼中用System.currentTimeMillis計算時間差。

結(jié)論 : 后臺慢,且查詢sql慢

sql有什么問題

  • sql拼接過長,達到了3000行,有的甚至到8000行,大多都是union all的操作,且有不必要的嵌套查詢和查詢了不必要的字段
  • 利用explain查看執(zhí)行計劃,where條件中除時間外只有一個字段用到了索引

備注 : 因優(yōu)化完了,之前的sql實在找不到了,這里只能YY了。

查詢優(yōu)化

去除不必要的字段

效果沒那么明顯

去除不必要的嵌套查詢

效果沒那么明顯

分解sql

  • 將union all的操作分解,例如(一個union all的sql也很長)

 

  1. select aa from bb_2018_10_01 left join ... on .. left join .. on .. where .. 
  2. union all 
  3. select aa from bb_2018_10_02 left join ... on .. left join .. on .. where .. 
  4. union all 
  5. select aa from bb_2018_10_03 left join ... on .. left join .. on .. where .. 
  6. union all 
  7. select aa from bb_2018_10_04 left join ... on .. left join .. on .. where .. 

將如上sql分解成若干個sql去執(zhí)行,最終匯總數(shù)據(jù),***快了20s左右。

 

  1. select aa from bb_2018_10_01 left join ... on .. left join .. on .. where .. 

將分解的sql異步執(zhí)行

利用java異步編程的操作,將分解的sql異步執(zhí)行并最終匯總數(shù)據(jù)。這里用到了CountDownLatch和ExecutorService,示例代碼如下:

  1. // 獲取時間段所有天數(shù) 
  2.        List<String> days = MyDateUtils.getDays(requestParams.getStartTime(), requestParams.getEndTime()); 
  3.        // 天數(shù)長度 
  4.        int length = days.size(); 
  5.        // 初始化合并集合,并指定大小,防止數(shù)組越界 
  6.        List<你想要的數(shù)據(jù)類型> list = Lists.newArrayListWithCapacity(length); 
  7.        // 初始化線程池 
  8.        ExecutorService pool = Executors.newFixedThreadPool(length); 
  9.        // 初始化計數(shù)器 
  10.        CountDownLatch latch = new CountDownLatch(length); 
  11.        // 查詢每天的時間并合并 
  12.        for (String day : days) { 
  13.            Map<String, Object> param = Maps.newHashMap(); 
  14.            // param 組裝查詢條件 
  15.  
  16.            pool.submit(new Runnable() { 
  17.                @Override 
  18.                public void run() { 
  19.                    try { 
  20.                        // mybatis查詢sql 
  21.                        // 將結(jié)果匯總 
  22.                        list.addAll(查詢結(jié)果); 
  23.                    } catch (Exception e) { 
  24.                        logger.error("getTime異常", e); 
  25.                    } finally { 
  26.                        latch.countDown(); 
  27.                    } 
  28.                } 
  29.            }); 
  30.        } 
  31.  
  32.  
  33.        try { 
  34.            // 等待所有查詢結(jié)束 
  35.            latch.await(); 
  36.        } catch (InterruptedException e) { 
  37.            e.printStackTrace(); 
  38.        } 
  39.  
  40.        // list為匯總集合 
  41.        // 如果有必要,可以組裝下你想要的業(yè)務數(shù)據(jù),計算什么的,如果沒有就沒了 

結(jié)果又快了20-30s

優(yōu)化MySQL配置

以下是我的配置示例。加了skip-name-resolve,快了4-5s。其他配置自行斷定

  1.  [client] 
  2. port=3306 
  3. [mysql] 
  4. no-beep 
  5. default-character-set=utf8 
  6. [mysqld] 
  7. server-id=2 
  8. relay-log-index=slave-relay-bin.index 
  9. relay-log=slave-relay-bin  
  10. slave-skip-errors=all #跳過所有錯誤 
  11. skip-name-resolve 
  12.  
  13. port=3306 
  14. datadir="D:/mysql-slave/data" 
  15. character-set-server=utf8 
  16. default-storage-engine=INNODB 
  17. sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 
  18.  
  19. log-output=FILE 
  20. general-log=0 
  21. general_log_file="WINDOWS-8E8V2OD.log" 
  22. slow-query-log=1 
  23. slow_query_log_file="WINDOWS-8E8V2OD-slow.log" 
  24. long_query_time=10 
  25.  
  26. Binary Logging. 
  27. # log-bin 
  28.  
  29. # Error Logging. 
  30. log-error="WINDOWS-8E8V2OD.err" 
  31.  
  32.  
  33. # 整個數(shù)據(jù)庫***連接(用戶)數(shù) 
  34. max_connections=1000 
  35. # 每個客戶端連接***的錯誤允許數(shù)量 
  36. max_connect_errors=100 
  37. # 表描述符緩存大小,可減少文件打開/關閉次數(shù) 
  38. table_open_cache=2000 
  39. # 服務所能處理的請求包的***大小以及服務所能處理的***的請求大小(當與大的BLOB字段一起工作時相當必要)   
  40. # 每個連接獨立的大小.大小動態(tài)增加 
  41. max_allowed_packet=64M 
  42. # 在排序發(fā)生時由每個線程分配 
  43. sort_buffer_size=8M 
  44. # 當全聯(lián)合發(fā)生時,在每個線程中分配  
  45. join_buffer_size=8M 
  46. # cache中保留多少線程用于重用 
  47. thread_cache_size=128 
  48. # 此允許應用程序給予線程系統(tǒng)一個提示在同一時間給予渴望被運行的線程的數(shù)量. 
  49. thread_concurrency=64 
  50. # 查詢緩存 
  51. query_cache_size=128M 
  52. # 只有小于此設定值的結(jié)果才會被緩沖   
  53. # 此設置用來保護查詢緩沖,防止一個極大的結(jié)果集將其他所有的查詢結(jié)果都覆蓋 
  54. query_cache_limit=2M 
  55. # InnoDB使用一個緩沖池來保存索引和原始數(shù)據(jù) 
  56. # 這里你設置越大,你在存取表里面數(shù)據(jù)時所需要的磁盤I/O越少.   
  57. # 在一個獨立使用的數(shù)據(jù)庫服務器上,你可以設置這個變量到服務器物理內(nèi)存大小的80%   
  58. # 不要設置過大,否則,由于物理內(nèi)存的競爭可能導致操作系統(tǒng)的換頁顛簸.   
  59. innodb_buffer_pool_size=1G 
  60. # 用來同步IO操作的IO線程的數(shù)量 
  61. # 此值在Unix下被硬編碼為4,但是在Windows磁盤I/O可能在一個大數(shù)值下表現(xiàn)的更好.  
  62. innodb_read_io_threads=16 
  63. innodb_write_io_threads=16 
  64. # 在InnoDb核心內(nèi)的允許線程數(shù)量.   
  65. # ***值依賴于應用程序,硬件以及操作系統(tǒng)的調(diào)度方式.   
  66. # 過高的值可能導致線程的互斥顛簸. 
  67. innodb_thread_concurrency=9 
  68.  
  69. # 0代表日志只大約每秒寫入日志文件并且日志文件刷新到磁盤.   
  70. # 1 ,InnoDB會在每次提交后刷新(fsync)事務日志到磁盤上 
  71. # 2代表日志寫入日志文件在每次提交后,但是日志文件只有大約每秒才會刷新到磁盤上 
  72. innodb_flush_log_at_trx_commit=2 
  73. # 用來緩沖日志數(shù)據(jù)的緩沖區(qū)的大小.   
  74. innodb_log_buffer_size=16M 
  75. # 在日志組中每個日志文件的大小.   
  76. innodb_log_file_size=48M 
  77. # 在日志組中的文件總數(shù).  
  78. innodb_log_files_in_group=3 
  79. # 在被回滾前,一個InnoDB的事務應該等待一個鎖被批準多久.   
  80. # InnoDB在其擁有的鎖表中自動檢測事務死鎖并且回滾事務.   
  81. # 如果你使用 LOCK TABLES 指令, 或者在同樣事務中使用除了InnoDB以外的其他事務安全的存儲引擎   
  82. # 那么一個死鎖可能發(fā)生而InnoDB無法注意到.   
  83. # 這種情況下這個timeout值對于解決這種問題就非常有幫助.  
  84. innodb_lock_wait_timeout=30 
  85. # 開啟定時 
  86. event_scheduler=ON 

被批準多久. # InnoDB在其擁有的鎖表中自動檢測事務死鎖并且回滾事務. # 如果你使用 LOCK TABLES 指令, 或者在同樣事務中使用除了InnoDB以外的其他事務安全的存儲引擎 # 那么一個死鎖可能發(fā)生而InnoDB無法注意到. # 這種情況下這個timeout值對于解決這種問題就非常有幫助. innodb_lock_wait_timeout=30# 開啟定時event_scheduler=ON

根據(jù)業(yè)務,再加上篩選條件

快4-5s

將where條件中除時間條件外的字段建立聯(lián)合索引

效果沒那么明顯

將where條件中索引條件使用inner join的方式去關聯(lián)

針對這條,我自身覺得很詫異。原sql,b為索引

 

  1. select aa from bb_2018_10_02 left join ... on .. left join .. on .. where b = 'xxx' 

應該之前有union all,union all是一個一個的執(zhí)行,***匯總的結(jié)果。修改為

 

  1. select aa from bb_2018_10_02 left join ... on .. left join .. on .. inner join 
  2.     select 'xxx1' as b2 
  3.     union all 
  4.     select 'xxx2' as b2 
  5.     union all 
  6.     select 'xxx3' as b2 
  7.     union all 
  8.     select 'xxx3' as b2 
  9. ) t on b = t.b2 

結(jié)果快了3-4s

性能瓶頸

根據(jù)以上操作,3天查詢效率已經(jīng)達到了8s左右,再也快不了了。查看mysql的cpu使用率和內(nèi)存使用率都不高,到底為什么查這么慢了,3天最多才60w數(shù)據(jù),關聯(lián)的也都是一些字典表,不至于如此。繼續(xù)根據(jù)網(wǎng)上提供的資料,一系列騷操作,基本沒用,沒轍。

環(huán)境對比

因分析過sql優(yōu)化已經(jīng)ok了,試想是不是磁盤讀寫問題。將優(yōu)化過的程序,分別部署于不同的現(xiàn)場環(huán)境。一個有ssd,一個沒有ssd。發(fā)現(xiàn)查詢效率懸殊。用軟件檢測過發(fā)現(xiàn)ssd讀寫速度在700-800M/s,普通機械硬盤讀寫在70-80M/s。

優(yōu)化結(jié)果及結(jié)論

  • 優(yōu)化結(jié)果:達到預期。
  • 優(yōu)化結(jié)論:sql優(yōu)化不僅僅是對sql本身的優(yōu)化,還取決于本身硬件條件,其他應用的影響,外加自身代碼的優(yōu)化。

小結(jié)

優(yōu)化的過程是自身的一個歷練和考驗,珍惜這種機會,不做只寫業(yè)務代碼的程序員。希望以上可以有助于你的思考,不足之處望指正。 

責任編輯:龐桂玉 來源: 數(shù)據(jù)庫開發(fā)
相關推薦

2019-12-13 10:25:08

Android性能優(yōu)化啟動優(yōu)化

2017-09-05 12:44:15

MySQLSQL優(yōu)化覆蓋索引

2009-04-20 08:51:50

MySQL查詢優(yōu)化數(shù)據(jù)庫

2018-01-09 16:56:32

數(shù)據(jù)庫OracleSQL優(yōu)化

2023-12-11 06:27:39

MySQL線上業(yè)務優(yōu)化后臺上傳文件

2021-07-16 23:01:03

SQL索引性能

2023-10-09 07:42:49

PawSQL數(shù)據(jù)庫管理

2022-07-04 23:24:28

sql優(yōu)化監(jiān)控

2018-04-19 09:02:14

SQL ServerSQL性能優(yōu)化

2023-11-28 07:54:18

2021-05-11 09:01:37

SQL優(yōu)化索引

2010-06-12 15:31:04

MySQL查詢優(yōu)化

2021-07-26 18:23:23

SQL策略優(yōu)化

2021-05-31 16:09:31

MySQLSchema設計

2022-10-17 00:00:00

SQLMySQL數(shù)據(jù),

2018-03-30 14:30:10

數(shù)據(jù)庫SQL語句性能優(yōu)化

2023-10-23 09:19:47

PawSQL數(shù)據(jù)庫

2023-11-07 07:50:55

LIMIT子句下推優(yōu)化

2018-03-30 13:59:22

數(shù)據(jù)庫SQL語句性能優(yōu)化

2018-03-30 18:17:10

MySQLLinux
點贊
收藏

51CTO技術棧公眾號