話不多說,上表:
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匯出 然後用...