3

人間が読める値を1つの列に格納し、同じテキストから特殊文字とスペースを取り除いたものを別の列に格納するルックアップに使用されるテーブルがあります。たとえば、値「Children's Shows」は、ルックアップ列に「childrens-shows」として表示されます。

残念ながら、対応するメインテーブルはそれほど単純ではありません。歴史的な理由から、自分で作成しなかったため、元に戻すのは困難です。ルックアップ値は、実際には「*children-shows*」のように周囲のアスタリスクとともに保存されます。

したがって、ルックアップテーブルのsans-asterisksをアスタリスクのあるメインテーブルに結合しようとしているときに、CONCATがそれらをオンザフライで追加するのに役立つと思いました。

    SELECT * 
      FROM main_table m 
INNER JOIN lookup_table l 
        ON l.value = CONCAT('*',m.value,'*')

...そしてテーブルはトーストでした。無限ループを作成したのか、実際にデータをねじ込んだのかはわかりませんが、テーブルを再度応答させるにはISPバックアップが必要でした。'*'記号はおそらくワイルドカードのように予約されているためだと思います。データベースに、自分の肘をなめるのと同じことをするように依頼しました。いずれにせよ、データベースを強制終了するという見事な方法を考えれば、私は「実験」で答えを見つけるのをためらっています。

(a)上記がデータベースに対して実際に何をしたか、および(b)実際にテーブルをどのように結合する必要があるかを教えてくれる人に事前に感謝します。

4

1 に答える 1

2

CONCATを使用する場合、mysqlはインデックスを使用しません。EXPLAINを使用してこれを確認しますが、最近の問題は、大きなテーブルにインデックス付きの列があり、キーが使用されていないことでした。ただし、これでテーブル全体が混乱することはありません。速度を落とすだけです。おそらく、メモリが不足し、スワップを開始し、途中でクラッシュしましたが、ログを確認して確認する必要があります。

ただし、根本的な原因は明らかに悪いテーブルデザインであり、そこに解決策があります。これを回避するために得られる答えは、せいぜい一時的なものにすぎません。

最善の解決策は、このデータを別のテーブルに移動することです。「子供向け番組」はカテゴリのように聞こえるので、多くの行でデータが繰り返されます。これは実際には「categories」テーブルのIDである必要があります。これにより、次のように、DBがテーブル内のすべての行でCONCATを実行する必要がなくなります。

    SELECT * 
      FROM main_table m 
INNER JOIN lookup_table l 
        ON l.value = m.value
   /* and optionally */
INNER JOIN categories cat
        ON l.value = cat.id
     WHERE cat.name = 'whatever'

あなたが質問で提供した情報を考えると、これはあなたができるかもしれないことではないことを私は知っていますが、実際には、正しく正規化されていないDBにそのような変更を加えることができない理由は、ここのコードよりも重要です。物事を正しい方法で行うためのリソースや政治的支援がなければ、このような頭痛の種はさらに多くなり、長期的にはより多くの費用がかかることになります。おそらく上司との言葉の時間:)

于 2012-10-17T10:18:01.800 に答える