2011-07-08 9 views
2

、3つのテキスト条件に合流これが私のクエリです:mysqlクエリを高速化するにはどうすればよいですか? 2〜3,000K記録

SELECT distinct decks.deckid, tmnt.tournamentid, tmnt.tournamentname, 
     cast(concat(Monthname(tournamentdate),' ',day(tournamentdate),', ', 
     year(tournamentdate)) as char) as ConfiguredTournamentDate, 
     tournamentdate, decks.pilot, decks.deckname, decks.record 
FROM tournaments tmnt 
LEFT JOIN decks on decks.tournamentid = tmnt.tournamentid 
LEFT JOIN cardsindeck cid on cid.deckid = decks.deckid 
WHERE upper(decks.deckname) like '%JULIAN23%' 
OR upper(decks.pilot) like '%JULIAN23%' 
OR upper(cid.cardname) like '%JULIAN23%' 
ORDER BY tournamentdate desc; 

このクエリが可能44Kの、12件の結果を返します。

  1. トーナメント - 2775の記録
  2. Deckname - 44400のレコードの
  3. Cardsindeck - 333万記録私がFULLTEXTインデックスが構築されている

(Iは、以下の説明が含まれます)。このクエリーには3〜6秒かかりますが、私の推測するレコードではそれほど悪くはありませんが、もっと速くするために何ができるかを見たいと思っています。データは1日に1回しか更新されません。その時点でテンポラリテーブルを作成してクエリすることができますか?

私はそれよりも頼りになる方法はありませんが、基本的に私がここで採用できる他の方法があるかどうかを見たいと思っていました。

はEXPLAIN:

1  SIMPLE tmnt ALL          2772 Using temporary; Using filesort 
1  SIMPLE decks ref  TourneyID_idx TourneyID_idx 5  magic_decks_july.tmnt.TournamentID  12 
1  SIMPLE cid  ref  DeckID_idx  DeckID_idx  5  magic_decks_july.decks.DeckID 24  Using where; Distinct 

UPDATE

これは0.5秒にクエリを削減しました。より受け入れられるMuuuuuch。今、他の3の問題領域に掘るために... :)

SELECT distinct decks.deckid, tmnt.tournamentid, tmnt.tournamentname, 
    cast(concat(Monthname(tournamentdate),' ',day(tournamentdate),', 
    ',year(tournamentdate)) as char) as ConfiguredTournamentDate, tournamentdate, 
    decks.pilot, decks.deckname, decks.record 
from tournaments tmnt 
inner join decks on decks.tournamentid = tmnt.tournamentid 
where decks.deckname like '%CONDESCEND%' 
OR decks.pilot like '%CONDESCEND%' 
UNION ALL 
SELECT distinct decks.deckid, tmnt.tournamentid, tmnt.tournamentname, 
    cast(concat(Monthname(tournamentdate),' ',day(tournamentdate),', 
    ',year(tournamentdate)) as char) as ConfiguredTournamentDate, tournamentdate, 
    decks.pilot, decks.deckname, decks.record 
from cardsindeck cid 
left join decks on cid.deckid = decks.deckid 
left join tournaments tmnt on decks.tournamentid = tmnt.tournamentid 
where cid.cardname like '%CONDESCEND%' 
order by tournamentdate 
+1

'' ---これは** **最適化することができません。ですから、適切な全文索引の使用法*に移行する必要があります。 – zerkms

答えて

0

... 
LIMIT 12 

を追加...また、私は事前に計算rsultsで、専用のテーブルを作成することは優秀で、最も簡単であることを考えますデータが1日に1回しか更新されない場合は、データが更新され、実行されるたびにテーブルを再計算するだけです。SELECT * FROM CACHED_DATA;

+0

また、上位の関数呼び出しを取り除くためにデータを大文字で入力できますか? –

+0

この制限は常に適用されるとは限りません - この特殊なクエリは12を返しますが、検索テキストは動的で、すべてを返すことができます。キャッシュされたテーブルのアイデアは、私が次に頭にいたところかもしれません。ありがとうございます。 –

+0

また、私は上部を取り除いたが、それは最小限の利益しかなかった(まだ5.1秒、私の心では ​​"平均"に落ちる)。それでも少し助けてくれれば助けになります。 –

1

結合ステートメント内でフィルタリングするようにクエリを書き直すと、より良い結果が得られるようです。現在のクエリ時間の

例、

SELECT * 
FROM (select now() query_time) qt 
INNER JOIN table_with_3mil_rows t1 ON value rlike "test" 
INNER JOIN smaller_table  t2 ON value rlike "test" 

副選択の背後にある理由は2つある。クエリのキャッシングを防止し、最も効果的な結果セット構築の開始時に最も多くのフィルタリングを行うことができます。

Mysqlはテーブルごとにquerysテーブルを作成します。したがって、最初のテーブルを開いて読み込むと、ON句が除外されている場合を除いてすべての行が読み込まれます。それから、次のテーブルを読み込み、右に参加しないものをフィルタリングし、それらをテーブルに追加し、結合が完了するまで続けます。

次に、where句によって呼び出されるフィルタリングを行います。

デッキ名を前面に並べるように並べ替えると、メモリ内のテーブルのサイズが小さくなり、クエリが高速化されます。

あなたのカードテーブルにpartioningを使用することもお勧めします。 3百万のレコードで、それは巨大です。

+0

私はパーティション化が大好きで、現時点では5.0になっており、移動するよりも大きな魚が揚げています。あなたの助けをありがとう、私は箱の外で考えるように私にインスピレーションを与えた! –

0

あなたの問題を助けるデッキIDのオフパーティショニングは、UPPERの使用である - それはためにwhere句にMySQLで

非常に高価であるすべての行を、呼び出され、like大文字小文字を区別しないで、 UPPERを使用しても、クエリには何の効果もありません。

はこれを試してみてください: '%JULIAN23%' のような

SELECT distinct decks.deckid, tmnt.tournamentid, tmnt.tournamentname, 
    cast(concat(Monthname(tournamentdate),' ',day(tournamentdate),', ', 
    year(tournamentdate)) as char) as ConfiguredTournamentDate, 
    tournamentdate, decks.pilot, decks.deckname, decks.record 
FROM tournaments tmnt 
LEFT JOIN decks on decks.tournamentid = tmnt.tournamentid 
LEFT JOIN cardsindeck cid on cid.deckid = decks.deckid 
WHERE decks.deckname like '%julian23%' -- Removed upper() usage 
OR decks.pilot like '%julian23%' -- Removed upper() usage 
OR cid.cardname like '%julian23%' -- Removed upper() usage 
ORDER BY tournamentdate desc; 
+0

ワイルドカード 'LIKE'クエリはまだ遅くなります。それらは何があってもテーブルスキャンを強制します。 – duskwuff

+0

はい、しかし、少なくとも処理がずっと少なくなっています – Bohemian

関連する問題