2017-08-27 7 views
2

他の左の記事を読んでゆっくりと記事を読んでください。mysqlは非常に遅いところで複数のテーブルに参加することを余儀なくされました

t_pbl_listは、IPサブネットブラックリストです。 800K行。

CREATE TABLE `t_pbl_list` (
    `_mask` tinyint(3) unsigned NOT NULL, #subnet 
    `_ipNet` int(10) unsigned NOT NULL, 
    `_attr` tinyint(3) unsigned NOT NULL, # bit0: exception 
    PRIMARY KEY (`_mask`,`_ipNet`), 
    KEY `ix_pbl_list` (`_mask`,`_ipNet`,`_attr`) 
) ENGINE=MEMORY DEFAULT CHARSET=latin1 

t_pbl_result IP結果一覧3.7M行..です

CREATE TABLE `t_pbl_result` (
    `_ip` int(10) unsigned NOT NULL, 
    `_utSlotAdd` mediumint(8) unsigned NOT NULL, 
    PRIMARY KEY (`_ip`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

私はt_pbl_listt_pbl_resultから_ipを選択されないようにしたいと思います。

このSQLはメモリ用の50代を取る理由を私は知りません。 Myisamが走れるように200秒。

1, SIMPLE, A, index, , PRIMARY, 4, , 3687929, Using index 
1, SIMPLE, B32, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B31, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B30, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B29, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B28, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B27, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B26, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B25, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B24, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B23, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B22, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B21, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B20, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B19, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B18, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B17, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B16, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B15, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B14, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B13, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B12, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B11, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B10, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B09, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, 
1, SIMPLE, B08, eq_ref, PRIMARY,ix_pbl_list, PRIMARY, 5, const,func, 1, Using where 

SQL:

SELECT 
A._ip 
FROM t_pbl_result AS A 
LEFT JOIN t_pbl_list AS B32 ON B32._mask = 32 AND B32._ipNet = A._ip >> 0 
LEFT JOIN t_pbl_list AS B31 ON B31._mask = 31 AND B31._ipNet = A._ip >> 01 
LEFT JOIN t_pbl_list AS B30 ON B30._mask = 30 AND B30._ipNet = A._ip >> 02 
LEFT JOIN t_pbl_list AS B29 ON B29._mask = 29 AND B29._ipNet = A._ip >> 03 
LEFT JOIN t_pbl_list AS B28 ON B28._mask = 28 AND B28._ipNet = A._ip >> 04 
LEFT JOIN t_pbl_list AS B27 ON B27._mask = 27 AND B27._ipNet = A._ip >> 05 
LEFT JOIN t_pbl_list AS B26 ON B26._mask = 26 AND B26._ipNet = A._ip >> 06 
LEFT JOIN t_pbl_list AS B25 ON B25._mask = 25 AND B25._ipNet = A._ip >> 07 
LEFT JOIN t_pbl_list AS B24 ON B24._mask = 24 AND B24._ipNet = A._ip >> 08 
LEFT JOIN t_pbl_list AS B23 ON B23._mask = 23 AND B23._ipNet = A._ip >> 09 
LEFT JOIN t_pbl_list AS B22 ON B22._mask = 22 AND B22._ipNet = A._ip >> 10 
LEFT JOIN t_pbl_list AS B21 ON B21._mask = 21 AND B21._ipNet = A._ip >> 11 
LEFT JOIN t_pbl_list AS B20 ON B20._mask = 20 AND B20._ipNet = A._ip >> 12 
LEFT JOIN t_pbl_list AS B19 ON B19._mask = 19 AND B19._ipNet = A._ip >> 13 
LEFT JOIN t_pbl_list AS B18 ON B18._mask = 18 AND B18._ipNet = A._ip >> 14 
LEFT JOIN t_pbl_list AS B17 ON B17._mask = 17 AND B17._ipNet = A._ip >> 15 
LEFT JOIN t_pbl_list AS B16 ON B16._mask = 16 AND B16._ipNet = A._ip >> 16 
LEFT JOIN t_pbl_list AS B15 ON B15._mask = 15 AND B15._ipNet = A._ip >> 17 
LEFT JOIN t_pbl_list AS B14 ON B14._mask = 14 AND B14._ipNet = A._ip >> 18 
LEFT JOIN t_pbl_list AS B13 ON B13._mask = 13 AND B13._ipNet = A._ip >> 19 
LEFT JOIN t_pbl_list AS B12 ON B12._mask = 12 AND B12._ipNet = A._ip >> 20 
LEFT JOIN t_pbl_list AS B11 ON B11._mask = 11 AND B11._ipNet = A._ip >> 21 
LEFT JOIN t_pbl_list AS B10 ON B10._mask = 10 AND B10._ipNet = A._ip >> 22 
LEFT JOIN t_pbl_list AS B09 ON B09._mask = 09 AND B09._ipNet = A._ip >> 23 
LEFT JOIN t_pbl_list AS B08 ON B08._mask = 08 AND B08._ipNet = A._ip >> 24 
WHERE 
(  # not in any subnet. 
     B32._mask IS NULL AND B31._mask IS NULL AND B30._mask IS NULL AND B29._mask IS NULL AND B28._mask IS NULL AND B27._mask IS NULL 
    AND B26._mask IS NULL AND B25._mask IS NULL AND B24._mask IS NULL AND B23._mask IS NULL AND B22._mask IS NULL AND B21._mask IS NULL 
    AND B20._mask IS NULL AND B19._mask IS NULL AND B18._mask IS NULL AND B17._mask IS NULL AND B16._mask IS NULL AND B15._mask IS NULL 
    AND B14._mask IS NULL AND B13._mask IS NULL AND B12._mask IS NULL AND B11._mask IS NULL AND B10._mask IS NULL AND B09._mask IS NULL 
    AND B08._mask IS NULL 
) 
OR 
(  # any subnet has exception attr. 
     B32._attr & 1 <=> 1 OR B31._attr & 1 <=> 1 OR B30._attr & 1 <=> 1 OR B29._attr & 1 <=> 1 OR B28._attr & 1 <=> 1 OR B27._attr & 1 <=> 1 
    OR B26._attr & 1 <=> 1 OR B25._attr & 1 <=> 1 OR B24._attr & 1 <=> 1 OR B23._attr & 1 <=> 1 OR B22._attr & 1 <=> 1 OR B21._attr & 1 <=> 1 
    OR B20._attr & 1 <=> 1 OR B19._attr & 1 <=> 1 OR B18._attr & 1 <=> 1 OR B17._attr & 1 <=> 1 OR B16._attr & 1 <=> 1 OR B15._attr & 1 <=> 1 
    OR B14._attr & 1 <=> 1 OR B13._attr & 1 <=> 1 OR B12._attr & 1 <=> 1 OR B11._attr & 1 <=> 1 OR B10._attr & 1 <=> 1 OR B09._attr & 1 <=> 1 
    OR B08._attr & 1 <=> 1 
) 
; 

どこで条件なしでクエリをしようとしました。 _attrを他のテーブルに結合した_ipだけを入れてください。遅いです。

ではなく、参加する場所での使用サブクエリをしようとしました。遅いです。

代わりにどこに参加するか試してみることはできません。遅いです。

試し削除>>操作機能。遅いです。

私は、内側がはるかに高速でし参加すると思いますが、私は同じテーブルですべてのテーブルを結合する必要があります。

+0

メモリとmyisamの選択は非常に慎重に思えますが、なぜあなたがそれらを選んだのか不思議です。 – Strawberry

+0

両方のテーブルのmyisaimでこのSQLを200秒実行します。リストテーブルのためにメモリに50秒かかる。私はmysqlについてあまり知らない。 't_pbl_list'は大きくないと思うので、メモリになる可能性があります。 't_pbl_result'は大事なもので、何か間違っていても大したことはありませんので、myisamです。 (innodbはトランザクションの方がいいですが、私はいつもadd、delete、myisamの方が速いかもしれないと思っています) – wa56

+0

ipが範囲内にあるかどうかを確認するために必要なレンジスキャンを賢く避けたと思います。基本的に高速な方法があるかどうかは不明です。しかし、 (2つの偶数マスクですべての奇数マスクを分割する)マスクだけを使用すると、結合数と半分の時間も削減されますが、リストを管理する作業が必要になることがあります。別のプロセスについて考えることもできます。現在の許可/ブロック状態を 't_pbl_result'に格納し、トリガを使ってその列を最新の状態に保ちます。もちろん、これらのリストの使い方にも依存します(たとえば、範囲を頻繁に編集する場合など)。 – Solarflare

答えて

0

私はt_pbl_resultからtipを選択します。これはt_pbl_resultにはありません。

おそらく、私は何かが欠けています。一度参加しないだけの理由はありますか?

SELECT  _ip 
FROM  (
       SELECT  res._ip 
          , lst._ipNet 
       FROM  t_pbl_result res 
       LEFT JOIN t_pbl_list lst ON 
          res._ip = lst._ipNet 
      ) t1 
WHERE  _ipNet IS NULL 
+0

@HodgePodgeありがとうございますが、rst._ipは192.168.0.5、lst._ipNetは192.168.0.0、lst._mask = 24と似ていますので、私はあらゆるマスクを試す必要があると思います。 – wa56

+0

@ Zheng Wangそれは複雑さを増します。 'SELECT _ip FROM(SELECT _ip FROM(SELECT A._ip、B32._ipNet) FROM t_pbl_result AS LEFT JOIN t_pbl_list AS B32 ON B32._mask = 32 AND B32._ipNet = A._ip >> 0)t1このクエリは大丈夫ですか? WHERE _ipNetはNULLではありません。それが大丈夫ならば、各サブステートメントを別々に実行し、最後に_ipリストを結合することが理にかなっています。 – HodgePodge

+0

thx、意味があります。しかし、それはちょうどB32、組合24回のために4秒かかります....そして、_attr&1 = 1も例外です。 – wa56

0

50秒?さて、3.7M * 24 JOINsにするには時間がかかります。

はt_pbl_list重複でip-範囲ですか?そうでない場合は、24回のテストではなく、1回のテストで各テストを実行できる最適化があります。それでも、3.7Mのテストがあります。 http://mysql.rjweb.org/doc.php/ipranges

関連する問題