2016-10-06 4 views
0

思えない加入:クエリは、バック与えるべきMySQLは遅い「OR」演算子が、労働組合または別の二人は、私は、MySQL内の任意のインデックスを使用していない「OR」演算子の典型的なパフォーマンスの問題を抱えているnoオプション

SELECT sms.smsID, sms.phonenumber, sms.text, date, mbr.name, mbr.prename 
FROM sms INNER JOIN (SELECT MAX(smsID) as smsID, phonenumber FROM sms 
group by phonenumber) sms2 ON sms.phonenumber = sms2.phonenumber AND 
sms.smsID = sms2.smsID 
LEFT JOIN mbr ON mbr.telephone = sms.phonenumber OR mbr.mobilphone = 
sms.phonenumber where sms.smsmodem = 'GSM1' 
order by date desc LIMIT 0,50 

を最後の50はSMSを受け取ったが、電話番号は1つしかなかった。次に、mbrテーブルに加入して、電話番号がmbrテーブルの人名に接続されているかどうかを調べる必要があります。とにかくmbrテーブルでは、電話番号は「電話」または「携帯電話」の列に表示される可能性があるので、両方を確認する必要があります。 Where句のOR演算子は、mbr.telephoneおよびmbr.mobilephoneの索引を使用しないため、問合せを20秒以上実行します。 SQL - left join with OR operator (MySQL)またはUNIONのように構築: MySql JOIN query with OR clause very slow

しかし、私は使用することはできません両方のケース

見つかりソリューションはLEFTを行うためのどちらかであるが、このように構築し、JOIN。

​​3210

組合のソリューションは、かつて(1などせずに、一度、送信者の名前で、ちょうど2つの列を返しますが、二回ごとに受信したメッセージを返します。左は、構築物が代わりに2つだけの4つの列が返されます参加します)他の意志ではない、MBRに対応する行を検索します選択:私は何とかこれらの「OR」演算子の問題は依然として2016年に存在していることを疑問に思って

SELECT sms.smsID, sms.phonenumber, sms.text, date, mbr.name,  
mbr.prename, mbr2.name, mbr2.prename FROM sms INNER JOIN (SELECT 
MAX(smsID) as smsID, phonenumber FROM sms group by phonenumber) sms2 ON 
sms.phonenumber = sms2.phonenumber AND sms.smsID = sms2.smsID LEFT JOIN 
mbr ON mbr.telephone = sms.phonenumber where sms.smsmodem = 'GSM1' 
UNION SELECT sms.smsID, sms.phonenumber, sms.text, date, mbr.name,  
mbr.prename, mbr2.name, mbr2.prename FROM sms INNER JOIN (SELECT 
MAX(smsID) as smsID, phonenumber FROM sms group by phonenumber) sms2 ON 
sms.phonenumber = sms2.phonenumber AND sms.smsID = sms2.smsID LEFT JOIN 
mbr ON mbr.mobilephone = sms.phonenumber where sms.smsmodem = 'GSM1' 
order by date desc LIMIT 0,50 

を...

答えて

0

OR非効率性がへ続きますeaがないので存在するsy(またはハード)溶液。組み込みのソリューションでも、UNIONの回避策のように見えます。

異なる視点からの解決策を見てみましょう。あなたは、 "列を横切って配列が広がっている"ようです。この場合、単純な2要素配列ですが、問題を引き起こしています。私は電話/携帯電話番号を指しています。

メインテーブルにそのような番号を持たず、代わりに別の番号のテーブルを持つことを検討してください。おそらく3つの列があります:smsID、number、およびnumber_type(必要な場合)。これにより、Numbersテーブルで単一の検索を実行してORを削除します。

クエリが「グループワイズ」であるように見えるので、効率的な方法で私のblogを指摘します。

+0

ありがとうございました。私は、データ構造を改造すること以外の可能性があると考えました。データベースとそれにアクセスするPHPスクリプトは1999年以来存在し、その時点ではo.kとみなされていました。各列に1つの連絡先の詳細(電話、携帯電話、電子メール、ファックス)を表す顧客テーブルを作成する。私はgroupwise_maxソリューションを見ていきます。サブクエリを使用したクエリの「手続き型SQL」はベストプラクティスではありませんが、パフォーマンスに関しては大きな問題ではありませんでした。 – Benedikt

+0

私は今、データベースへの2つのクエリを作成し、結果配列のキーをsmsIDに書き換え、foreachを使用して結果配列の1つをループし、両方のいずれかで利用できる名前情報があるかどうかを確認することで、この各smsIDの結果配列を取得し、両方の結果から結果配列を構築します。最小の実行時間で動作します。 まだそれは私の気持ちをそんなやり方で傷つけます。 ;-) – Benedikt

関連する問題