關於兩張3億資料表的關聯查詢優化

2021-09-27 01:50:18 字數 3466 閱讀 6017

話不多說,上表:

factor_status_log_to_reason(3億條資料):

create

table

`factor_status_log_to_reason`

(`fsl_id`

int(11)

unsigned

notnull

,`reason_id`

int(11)

unsigned

notnull

,primary

key(

`fsl_id`

,`reason_id`))

engine

=innodb

default

charset

=utf8

factor_status_log(2億條資料):

create

table

`factor_status_log`

(`fsl_id`

int(11)

unsigned

notnull

auto_increment

,`object_key`

varchar

(255

)not

null

,`operator_name`

varchar(32

)not

null

,`operation_id`

int(11)

unsigned

notnull

,`products_id`

int(11)

unsigned

notnull

,`mc_id`

int(11)

unsigned

notnull

,`object_status`

int(11)

default

null

,`date_added`

timestamp

notnull

default

'1999-09-09 00:00:00'

,primary

key(

`fsl_id`),

key`idx_objk`

(`object_key`),

key`idx_pm`

(`products_id`

,`mc_id`),

key`idx_date`

(`date_added`))

engine

=innodb

auto_increment

=343169419

default

charset

=utf8

不要在意為啥乙個表這麼多資料,因為他就是有這麼多資料,沒有分庫分表

第一版sql:

select

*from factor_status_log fsl join factor_status_log_to_reason fsltr on fsltr.fsl_id = fsl.fsl_id and fsltr.reason_id in(67

,64)limit

10;

執行之後發現巨慢,用explain檢視執行計畫如下:

idselect_type

table

type

possible_keys

keykey_len

refrows

extra

1******

fslall

primary

null

null

null

207636393

1******

fsltr

refprimary

primary

4products_center_v1.fsl.fsl_id

1using where; using index

不理解為啥乙個表沒有走索引,過濾條件都是加索引的呀。

接下來進入了短暫的捋原理階段:

兩個表鏈結的原理是這樣的,如果是外連線,那麼可以自己選定一張表作為驅動表,如果是內連線,mysql會選定一張表作為驅動表。比如以上 我寫的sql是內連線,那個表是驅動表呢?看explain第一條的表fsl就是驅動表。

選定驅動表之後,會對驅動表進行單錶掃瞄,掃瞄出結果。比如掃瞄出兩條資料fsl_id = 1,2。

然後才能利用到關聯條件fsltr.fsl_id = fsl.fsl_id,對被驅動表進行兩次查詢,也就是fsltr.fsl_id = 1,fsltr.fsl_id = 2。如果驅動表找出一萬條資料,那麼被驅動表就需要查詢一萬次。有沒有感覺到其實這就像是乙個巢狀迴圈?對滴,這種查詢就叫迴圈巢狀查詢。

原理知道了,為啥咱寫的說sql慢呢?根本原因就是在mysql首先對驅動表factor_status_log進行單錶查詢的時候,並沒有對其用索引條件進行過濾,就相當於

select

*from factor_status_log;

並不會走索引,所以是全表掃瞄。

優化:

select

*from factor_status_log_to_reason fsltr ,factor_status_log fsl where fsl.date_added <

'2019-01-07 00:00:00'

and fsl.date_added >

'2018-06-07 00:00:00'

and fsltr.fsl_id = fsl.fsl_id and fsltr.reason_id in(67

,64)limit

10;

目的是對驅動錶用索引date_added進行過濾一下。執行計畫如下:

idselect_type

table

type

possible_keys

keykey_len

refrows

extra

1******

fslrange

primary,idx_date

idx_date

4null

61972696

using where

1******

fsltr

refprimary

primary

4products_center_v1.fsl.fsl_id

1using where; using index

可以看到單錶掃瞄是range,並且走了索引idx_date。

可以在幾秒之內出結果了。

聯合刪除兩張表的資料

大家都知道delete後面不能跟多張表,但有時刪除資料時要同時維護多張表的資料,這怎麼辦呢?假設 a,b兩張表,它們通過id進行關聯,a表中有名稱欄位而b表中沒有,現根據時間段刪除資料 sql declare delid table id int delete a output deleted.id...

oracle兩張表的資料比較

資料庫 oracle 在某些情況下,我們會需要比較兩張表的資料是否一樣。假設有兩張表a與表b他的字段相同,但是當中的資料可能不同,而且有些欄位的資料還有可能為空 方法一 手動 把需要比較的兩張表的資料按照某種規則排序後匯出為xls,這裡我直接用pl sql developer匯出 然後用把xls檔案...

oracle兩張表的資料比較

align left align 在某些情況下,我們會需要比較兩張表的資料是否一樣。假設有兩張表a與表b他的字段相同,但是當中的資料可能不同,而且有些欄位的資料還有可能為空 方法一 手動 把需要比較的兩張表的資料按照某種規則排序後匯出為xls,這裡我直接用pl sql developer匯出 然後用...