乙個 20 秒 SQL 慢查詢優化處理方案

2022-09-20 10:33:10 字數 1831 閱讀 1573

目錄

頁面無法正確獲取資料,經排查原來是介面呼叫超時,而最後發現是因為sql查詢長達到20多秒而導致了問題的發生。

這裡,沒有高深的理論或技術,只是備忘一下經歷和解讀一些思想誤區。

這裡不過多對業務功能進行描述,但為了突出問題所在,會用模擬的語句來描述當時的場景

複雜的sql語句可以表達如下:

select * from a_table as a

left join b_table as b on a.id=b.id

where a.id in (

select distinct id from a_table

where user_id in (100,102,103) group by user_id h**ing count(id) > 3

)從上面簡化的sql語句,可以看出,首先進行的是關聯查詢。

其次,是巢狀的子查詢。此子查詢是為了找出多個使用者共同擁有的組id。所以語句中的「100,102,103」是根據場景來定的,並且需要和後面「count(id) > 3」的個數對應。簡單來說就是找使用者交集的組id。

程式設計客棧假設現在a_table表的資料量為20w,而b_table的資料量為2000w。大家可以想一下,你覺得主要的耗時是在關聯查詢部分,還是在子查詢部分?

(思考空間。。。。)

(思考空間。。。。。。。)

(思考空間。。。。。。。。。。)

對於sql底層的原理和高深的理論,我暫時掌握不夠深入。但我知道可以通過模擬和簡單的測試來驗證是哪一塊環節出了問題。

首先,對於只有乙個使用者id時,我會把上面的語句簡化成:

elect * from a_table as a

left join b_table as b on a.id=b.id

where user_程式設計客棧id in (100)

所以,初步斷定應該是巢狀的子查詢部分占用了大部分的時間。

既然定位到了是巢狀的子查詢語句的問題,那又要分為兩塊待排查的區域:是子查詢本身耗時大,還是巢狀而導致慢查詢?

結果很容易發現,當我把子查詢單獨在db中執行時,是非常快的。所以排除。

剩下的不言而喻,20秒的慢查詢是巢狀引起的。

但因為處於上線緊急的過程中,為了確保,我快速地驗證了我的結論:

well done!  準備修復上線!

線上的問題,很多時間都是在定位問題和分析原因,既然問題找到了,原因也找到了,解決方案不言而喻。**簡單處理即可。

當前,實際的sql語句,會比這個更為複雜,但已足以表達問題所在。但在前期,筆者也做程式設計客棧了一些sql的**。

因為b_table比a_table大,所以一開始b_table左關聯a_table時,很慢,大概是1秒多,而且資料量是很少的;但若反過來,a_table左關聯b_table時,則很快,大概是100毫秒。

所以,又發現乙個有趣的現象:

大表 左關聯 小表,很慢;小表 左關聯 大表,很快。

當然,這些我們理論上都知道,但實際開發會忘卻。又或者一開始兩個表都為空時,而又沒考慮到後期這兩個表增長的速度時,日後就會埋下坑了。

總結:首先,巢狀的子查詢是很慢的。

原因,我還沒仔細去研究,但在下班的路上和我的同事交流時,他說曾經看過這方面相關的書籍,是說每一次的子查詢都會產生乙個sql語句,所以就n次查詢了。而另外一位資深的qa同事則跟我說,應該是m*n的問題。

其次,我一開始使用巢狀子查詢,是存在這樣乙個誤區:我覺得將這些操作交給mysql自身來處理會更高效,畢竟db內部會有良好的機制來執行這些查詢由。

然後,實際表白,我錯了。因為這不是簡單的合併mc批量查詢。

當我們決定使用一些底層的技術時,只有當我們理解透徹了,才能使用更為恰當。而因為無知就斷定工具、框架、底層無所不能時,往往就會中招。

乙個sql的優化

原文 乙個sql的優化 目的 為了查詢某天某個伺服器上的登入id的個數 剛開始編寫的sql select count a.mac logusers from log maclogin all a where ismoni 1 and logintime 2015 02 01 23 59 59 and...

SQL 記乙個查詢問題

有部門表和部門管理員表,部門表比較常規,反常的是部門管理員表。這張表是etl整理出來的表,包含各部門的主管 秘書 機要員資訊等等。下面把關鍵字段列出來 部門表,department dept code dept name 50040001 部門150040002 部門250040003 部門3部門管...

乙個db的查詢優化記錄

h2 db中有乙個表 create table asset asset numeric real numeric timestamp numeric timestring varchar 100 其中timestamp是unixtime,表的索引是timestamp 需要將某天之前的最後一條記錄找出...