2017-08-21 4 views
4

MySQL 5.7では奇妙な動作(バグ?)が発生しましたが、これはMySQL 5.5では表示されません。LEFT JOINを使用してクエリを実行すると、MySQL EmptyテーブルがTRUEを返します。

だから私はそれを説明するための例が必要です。

  1. 左を使用してテーブルを作成して2つのテーブルに参加
  2. は、第二のテーブルが空である(レコードなし)が、それの分野の一つで書かれた静的な値を持つことにより構成されていることを確認します。

左(予想通り)がNラインを生成ない条件

決してはまた、Nラインを生成一致しない状態との結合との結合します。

### EXAMPLE ### 

## CREATE TABLES 

create table PCPL (K1 int); ## Table 1 
create table AUX (K2 int); ## Table 2 

## FILL IN TABLES 

insert into PCPL values (1),(2),(3); ## fill main table with 3 values 
truncate table AUX;      ## No need to do this, just to make things clearer 

## TEST 1 : "Dry Left join" => RESULT OK : Resulting Table has 3 rows 

select PCPL.K1 as K1 , DERIVED.K2 as K2 
from PCPL 
LEFT JOIN (select K2, 1 as staticValue from AUX) DERIVED 
ON PCPL.K1 = DERIVED.K2; 

+------+------+ 
| K1 | K2 | 
+------+------+ 
| 1 | NULL | 
| 2 | NULL | 
| 3 | NULL | 
+------+------+ 
3 rows in set (0,00 sec) 


## TEST 2 : "Never matching condition" => STRANGE : Resulting Table NOT empty 

select PCPL.K1 as K1 , DERIVED.K2 as K2 
from PCPL 
LEFT JOIN (select K2, 1 as staticValue from AUX) DERIVED 
ON PCPL.K1 = DERIVED.K2 
where staticValue=1; ##### THIS CONDITION IS NEVER MET SINCE TABLE AUX IS EMPTY 

+------+------+ 
| K1 | K2 | 
+------+------+ 
| 1 | NULL | 
| 2 | NULL | 
| 3 | NULL | 
+------+------+ 
3 rows in set (0,00 sec) 

THIS SHOULDN'T HAPPEN ! 

この動作は、MySQL 5.5

では発生しません。これは私が5.7に設定するのを忘れ5.5のバグか、いくつかのパラメータですか?

ありがとうございました!

+1

が見えます。私はIS NOT NULLに対して1を変更し、まだすべての行を持ちますが、staticValueの値は実際にはNULLではないようです。 http://rextester.com/XPM1274 'version()= 5.7.12-log' –

+0

こんにちは、あなたは私と同じ振る舞いをしていますか? 5.7.18-log MySQLコミュニティサーバ(GPL) –

+0

はい、同じ動作です。 Rextesterを確認してください –

答えて

2

これは、特にサブクエリマージのバグのようです。これは、MySQLがサブクエリを実現するオーバーヘッドを避けるための戦略です。

select PCPL.K1 as K1, DERIVED.K2 as K2, 
     (CASE WHEN DERIVED.K2 IS NULL THEN 'is null' ELSE 'not null' END) as K2_null, 
     staticValue 
     (CASE WHEN staticValue IS NULL THEN 'is null' ELSE 'not null' END) as staticValue_null 
from PCPL LEFT JOIN 
    (select K2, 1 as staticValue from AUX) DERIVED 
    ON PCPL.K1 = DERIVED.K2 
where staticValue IS NOT NULL; 

そしてDERIVEDの唯一の違いは、この改変された形態:

select PCPL.K1 as K1, DERIVED.K2 as K2, 
     (CASE WHEN DERIVED.K2 IS NULL THEN 'is null' ELSE 'not null' END) as K2_null, 
     staticValue 
     (CASE WHEN staticValue IS NULL THEN 'is null' ELSE 'not null' END) as staticValue_null 
from PCPL LEFT JOIN 
    (select K2, 1 as staticValue from AUX order by k2 limit 3) DERIVED 
-------------------------------------------^XXXXXXXXXXXXXXXXXX 
    ON PCPL.K1 = DERIVED.K2 
where staticValue IS NOT NULL; 

order by k2 limit 3の目的は、強制的にです

は、次の2つのクエリを(最初は、元である)を検討しますサブクエリのマテリアライゼーション最初のバージョンは3行(不正確)を返します。 2番目のバージョンはゼロ行を返します(正しい)。どちらの場合も、サブクエリは同じ行セットを返します。

違いは、強制的なマテリアライゼーションが問題を解決することです。したがって、これはサブクエリマージのバグのように見えます。

documentationでサブクエリマージについて読むことができます。

小さな編集ノート。洗練されたデータベースは、処理を記述するDAG(有向非循環グラフ)にクエリを解析します。次に、操作をグラフで操作するための洗練されたルール、特にフィルター操作と列計算があります。

MySQLはクエリのより単純なモデルから始まります。開発者はより洗練されたモデルに移行しています。このような小さなバグは予期しないことではありませんが、それを解決するにはバージョンまたは2が必要です。

0

多くのありがとうございます。変数optimizer_switchにderived_mergeの設定を解除してバグが1のoccuringからそれを防ぐことができ、固定されている待っている間、あなたがここにバグを持っているよう

SET @@optimizer_switch='block_nested_loop=off'; 
関連する問題