在此說是攻略式思考,是因為僅供參考,說是攻略,是因為暫時還沒有嚴謹的結論,目前只能說對結論有幫助。
問題簡單復現下:
建立乙個表users,然後插入一些資料之後,使用兩種方式來對比下:
create table users(userid int(11) unsigned not null,user_name varchar(64) default null,primary key(userid))engine=innodb default charset=utf8;如果要插入資料,可以使用儲存過程的方式。比如先插入20000條定製資料。delimiter $$drop procedure if exists proc_auto_insertdata$$create procedure proc_auto_insertdata()begindeclareinit_data integer default 1;while init_data<=20000 doinsert into users values(init_data,concat('user' ,init_data));set init_data=init_data+1;end while;end$$delimiter;call proc_auto_insertdata();初始化的過程會很快,最後一步即插入資料花費了近6秒的時間。[test]>source insert_proc.sqlquery ok, 0 rows affected (0.12 sec)query ok, 0 rows affected (0.00 sec)query ok, 0 rows affected (0.00 sec)query ok, 1 row affected (5.63 sec)然後我們使用如下的半連線查詢資料,實際上執行了6秒左右。select u.userid,u.user_name from users u where u.user_name in (select t.user_name from users t where t.userid<2000);1999 rows in set (6.36 sec)
在ssd的環境上,時間在2.58秒左右。為了簡化測試條件和查詢結果,我們使用count的方式來完成對比測試。[test]>select count(u.userid) from users u where u.user_name in (select t.user_name from users t where t.userid<2000);+-----------------+| count(u.userid) |+-----------------+| 1999 |+-----------------+1 row in set (6.38 sec)然後使用如下的方式來檢視,當然看起來這種結構似乎有些多餘,因為userid
其實對於第二種方法來說,我們似乎只看到了結論,但是沒有乙個基本的參考點。如果按照這個思路,應該會得出mysql優化器很low的印象。
對於這個問題該怎麼解釋呢。這個條件 or u.user_name in (select t.user_name from users t where userid
其實是有的,如果我這麼寫這個sql:
mysql> select count(u.userid) from users u where (u.user_name in (select t.user_name from users t where t.userid<2000) or isnull(null));
| count(u.userid) |
| 20000 |
1 row in set (0.00 sec)
這個邏輯還是能夠基本接受的,其實算是找到了乙個基本的規律吧。
當然這個問題為什麼這麼解讀呢。
我們使用explain extended來解讀,常規的語句會被解析成為標準的semijoin的格式。
| note | 1003 | /* select#1 */ select `test_bug`.`u`.`userid` as `userid`,`test_bug`.`u`.`user_name` as `user_name` from `test_bug`.`users` `u` semi join (`test_bug`.`users` `t`) where ((`test_bug`.`u`.`user_name` = ``.`user_name`) and (`test_bug`.`t`.`userid` < 2000))
其實這種方式我們無法得到semijoin的更多資訊。我想起了之前處理乙個反連線的問題時,通過explain extended得到的查詢重寫資訊。
這是乙個反連線的語句,即not in
原來的語句如下:
select account from t_fund_info where money >=300 and account not in(select distinct(login_account) from t_user_login_record where login_time >='2016-06-01')into outfile '/tmp/data.txt';
解析後的結果如下,可以明顯看到解析後的結果比原語句要複雜了好多。
其中or isnull()的部分引起了我的好奇。這個不就是我們之前有效果的半連線場景嘛,這裡是反連線,只是在外部多了乙個not的反向操作,對於這個小的發現也是如獲至寶,至少對於我處理一些半連線的問題有了更多的思路和借鑑,後續可以看看**裡的解析方法。
MySQL半同步複製
1 從mysql5.5開始,mysql以外掛程式的形式支援半同步複製。如何理解半同步呢?首先我們來看看非同步,全同步的概念 非同步複製 asynchronous replication mysql預設的複製即是非同步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收...
檢視mysql半杯 MySQL同步資料
mysql dump工具用於匯出現有資料,匯出結果為sql檔案 目前dump工具支援整庫dump以及單錶dump。下面為單錶dump操作過程 1 選擇匯出目標目錄 確保該目錄有足夠的儲存空間。mkdir opt bas backup 2 使用mysqldump命令匯出表資料 mysqldump u ...
MySQL 複製過濾和半同步複製
半同步複製主要是為了考慮和解決主從資料一致性的問題,5.5 5.6版本出現的這個功能,然後在5.7版本以後因為出現了mgr複製,就完全的被mgr進行代替了,現在主要是跟mgr進行對比的。半同步複製和普通主從的說明 1 普通主從 主庫dump thread傳送給io thread資料,io接收到資料寫...