【最大10000ポイント】当たる!!質問投稿キャンペーン!

SQLの処理速度があまりに遅い(最悪1分以上かかる)ので
わかる方がいらっしゃいましたらアドバイスをお願いいたします
MySQL4になります-----------------------
-- 問題SQL

SELECT COUNT(*) as count FROM
(
SELECT id, word FROM
(
SELECT distinct tbl.id, p.word
FROM table01 tbl INNER JOIN table02 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
UNION
SELECT distinct tbl.id, p.word
FROM table11 tbl INNER JOIN table12 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
) test1
UNION
SELECT id, word FROM
(
SELECT distinct tbl.id, p.word
FROM table21 tbl INNER JOIN table22 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
UNION
SELECT distinct tbl.id, p.word
FROM table31 tbl INNER JOIN table32 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
UNION
SELECT distinct tbl.id, p.word
FROM table41 tbl INNER JOIN table42 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
UNION
SELECT distinct tbl.id, p.word
FROM table51 tbl INNER JOIN table52 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
) test2 GROUP BY word
) A

----------------------

既存のテーブルが、table01~table51(各テーブルに付随するサブテーブルでtable02~table52がある感じ)まであり
その各テーブル内に存在しているカラムkeyword(varcharで NOT NULL、indexは張ってある)の一文字だけを指定し検索結果の件数を取得したいのですが
速度があまりに遅く、悩んでおります。
2文字以上だと若干重いかなという感じがするだけです
(実際のSQLはもっとごちゃごちゃしており、見やすくするため不必要なカラム等削除しております)

table01は51万レコード、table11は、175万レコードあります。
(その他は1万レコード程度です)
そもそもこの件数をLIKE検索で行っていること自体、おかしいのですが
もうどうしようもないので、このSQLをなんとか修正したいと考えております

目標としては、
この旧SQLと新SQLで取得した件数が同じになり、かつ速度が上がることにあります

「 ) test2 group by word 」については、table21~table51で重複するwordを削除したいという意向があり、ついております
(table01とtable11と一緒にunionして、group byしたくないです)




私のほうで修正・実行した方法は、

1)SELECT count(*) as count from を SELECT count(id) as count from と*を止める指定する
2)test1とtest2内のSELECTで取得するカラムを最小限にする(上記のものはかなり少なくしてあり、もうこれ以上減らせません…)
3)test1内のSQLでtable01、table11をunionしているところを、分割する

↓こんな感じに分割
SELECT count(id) as count from
(
select id, word from
(
SELECT distinct tbl.id, p.word
FROM table01 tbl INNER JOIN table02 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
) test1
union
select id, word from
(
SELECT distinct tbl.id, p.word
FROM table11 tbl INNER JOIN table12 p ON p.id = tbl.id WHERE keyword LIKE 'a%'
) test2
union
select id, word from
(




となります。
一応、60秒程度掛かっていたものが、5~20秒程度で帰ってくるようにはなりましたが
まだまだ実用には耐えられない状況です

もしまだ改善すべき箇所等ございましたらアドバイスをおねがいいたします

よろしくお願いいたします

このQ&Aに関連する最新のQ&A

A 回答 (1件)

まずMySQL4って一番最悪のバージョンですが本当に大丈夫ですか?


とくにMySQL4.0とMySQL4.1は似たバージョンですが中身はほぼ別物で
もし4.0をつかっているなら高速化はかなり難しいと思います。

MySQL4使うくらいならMySQL3.23の方がチューニングしやすいと思います。
MySQL5以降の適当な運用を検討した方がよいと思いますが・・・

ちなみにSQL文的にもUNIONでつないだものを集計するのは相当無理があるように見えます
なぜ同じ様な構成のテーブルを冗長に分断してしまったのでしょうか?
構成がおなじならパーティショニングなどで統合して管理した方がよいのでは?

あとはexplainで様子を見ながらチューニングしていくのが賢明でしょう
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVIEWの元のテーブルのindexって有効なのでしょうか?

VIEWの元のテーブルのindexって有効なのでしょうか?
MYSQLサーバのバージョンは5.0.77です。
どうぞよろしくお願いします。

Aベストアンサー

ビューの基表に、有効活用できるインデクスがあれば、インデクスは活用されます。

>例えば元のテーブルに「hoge_id(index)」があり、
>VIEWテーブルが「vtable」だとします。

>SELECT * FROM vtable WHERE hoge_id = 値
>または、
>SELECT * FROM vtable LEFT JOIN atable ON vatble.hoge_id = atable.id
>(atable.idもindex)

>などとした場合、hoge_idのindexが有効で高速に結果が返ってくるということでよろしいのでしょうか。

表の母体データ件数が相当に少ない(例えば、数百件など)とか、重複キー値が多量に存在するといった場合は、RDBMSのオプティマイザが、「インデクスを使うより、テーブルスキャン(表のデータを全件サーチ)した方が速い」と判断し、インデクスを利用しない場合もあります。

主キーなどユニークなキーでの「=」条件や範囲条件などで、母体データからある程度絞り込んだ検索をするなら、インデクスの活用で母体データが大量に増えても、一定の性能を出せます。

ビューの基表に、有効活用できるインデクスがあれば、インデクスは活用されます。

>例えば元のテーブルに「hoge_id(index)」があり、
>VIEWテーブルが「vtable」だとします。

>SELECT * FROM vtable WHERE hoge_id = 値
>または、
>SELECT * FROM vtable LEFT JOIN atable ON vatble.hoge_id = atable.id
>(atable.idもindex)

>などとした場合、hoge_idのindexが有効で高速に結果が返ってくるということでよろしいのでしょうか。

表の母体データ件数が相当に少ない(例えば、数百件など)とか、重複キー値...続きを読む

QデータベースのINT型項目にNULLはNG?

以前、知り合いからデータベースのINT型の項目には出来ればNULLを許可しない(NOT NULL)方がいいと聞いたことがあるのですが、本当でしょうか?

現在不動産の物件データを登録するためのシステムを作成しており、
データベースの設計を行なっている最中なのですが、
例えば金額や面積など数字しか入力されない項目はINT型にしたいと考えています。
※データベースはMySQLになります。

ただし、
物件データ登録時に数字項目に何も入力されなければ「NULL」、
0以上の数値を入力されている場合にはそのままその数値をデータベースに登録したいと考えています。
※0を入力されている場合には「0」をそのまま入れたいです。

INT型の項目にはNULLを入れるのを避けた方がいい場合には、0を入れるような仕様に変更しようと考えているのですが、その辺のことについて教えて頂けると助かります。

ざっくりとした質問で申し訳ございませんが、宜しくお願い致します。

Aベストアンサー

物件データ登録時に数字項目に何も入力されなければ「NULL」、0を入力されている場合には「0」
本来の意図としては正しいはずです。
Nullは本来、どの値を入れればいいのかわからない値ということなので、
数字がわからない=何も入力していない ということで、Nullを指定するのは正しいはずです。
しかし、
実際に使うときには、Nullは実に不自由なので、
Nullは使うなという話がでてきます。
## 私なら、入力区分 0=未入力、1=入力 と 数値(未入力は0)と別々に持つかもしれません。

というのは例えば、
金額 100万以上の物件は何件?
というSQLに対して、100件と答えがでて、
金額 100万未満の物件は何件?
というSQLに対して、50件と答えがでたとします。
じゃあ、全物件は?・・・172件だったりします。
何故?⇒Nullが22件だったためです。
(Nullは0とは違い、どちらの検索条件にも含まれません。)
・・・この不自由さを回避するために数値項目に、Not Null制約をつけることが多いです。

QInner join と Left joinの明確な違いは?

Inner join と Left joinの違いがよくわかりません。
教えてください。

Aベストアンサー

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
4               NULL
5               NULL
6               NULL
の6レコードが出力されますが、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 INNER JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
の3レコードしか出力されません。

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3           ...続きを読む

QDBエラーの意味

フォームからDBにデータ挿入しようとすると

Column count doesn't match value count at row 1

というエラーが出てしまいます・・・どういう意味を持ったエラーなんでしょうか?

Aベストアンサー

カラム数と値の数が合わない、と言う事です。簡単な英語なので覚えましょう。
カラム数が4つにもかかわらず、
"INSERT INTO tablename VALUES (1,'hoge',3)"
とやった場合等に出るエラーだと思います。

QHTMLフォームのSELECTの幅を一定にするためには?

HTMLフォームのSELECTの幅を一定にするためにはどのようにすれば
いいのでしょうか?

CSS等で設定できるとありがたいのですが、やり方がわかりません。

Aベストアンサー

<select style="width: 200px">

Qpingでポートの指定

pingでIPアドレスを指定して、通信できるかどうかというのは
よく使いますが、pingでポートを指定して応答するかどうかは調べられるのでしょうか?

よろしくお願いします

Aベストアンサー

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含むICMP)ではできません。

FTPの疎通確認であれば、クライアントからサーバに対するTCP/21通信(FTP-CMD)が可能であること(サーバからクライアントへのTCP/21からの応答を含む)+サーバからクライアントに対するTCP/20通信(FTP-DATA)が可能であること(クライアントからサーバへのTCP/21からの応答を含む)が必要でしょう。

監視ソフトによるものであれば、
・クライアントからサーバへのログイン(TCP/21)
・クライアントからサーバへのlsの結果(TCP/20)
で確認すればよいでしょう。

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含む...続きを読む

Q「いずれか」と「いづれか」どっちが正しい!?

教えて下さいっ!
”どちらか”と言う意味の「いずれか」のかな表記として
「いずれか」と「いづれか」のどちらが正しいのでしょう???

私は「いずれか」だと思うんですが、辞書に「いずれか・いづ--。」と書いてあり、???になってしまいました。
どちらでもいいってことでしょうか?

Aベストアンサー

「いずれか」が正しいです.
「いづれ」は「いずれ」の歴史的かな遣いですので,昔は「いづれ」が使われていましたが,現代では「いずれ」で統一することになっていますので,「いずれ」が正しいです.

QCSVファイルの中で、「 , 」カンマを使いたい

「 , 」で区切られたCSVファイルの中で、「 , 」カンマを使いたいのですが、可能でしょうか?

具体的には「これは1,500円でした。」というように、CSVファイルに収められた文章内で出てくる半角の数字(お金)の区切りに使いたいのです。
全角では代用したくないのですが、CSVファイルでデータを受け渡しする際に、困っています。

例えば、特殊文字などで対応可能でしょうか?

Aベストアンサー

受け渡しに使うと言うことは相手方のアプリケーションのことも考えなければいけないのですが・・・とりあえず対応が簡単そうな方法を。

1.各セルを""で囲む。(もちろんデータにダブルクォートがある場合はカンマと同様に困ります。
2.カンマで区切らずにタブで区切る。(比較的使われない文字ですが、やはりデータ中にタブがあるとカンマと同様です)

難しいけれど完璧に対応するためには、データ中の区切り文字は特殊な文字列に変更し、受け取り側のアプリケーションではその特殊な文字列をデータ中の区切り文字として扱うという方法が使われます。
例えば、データ中のカンマは\,にするとか。

データ作成側、受け取り側でそれぞれどこまで対応できるのか分かるともっと簡単かつ具体的な方法を回答できるかも知れません。

QMySQL5.1.14で空白を入れるとエラーになる

MySQL5.1.14をインストールをしたところ、4.1で動いていたプログラムが軒並みエラーストップ。
どうも、空白を入れるとエラーになるようで、5.1へ移行出来なくて困っています。どなたかご教授をお願いします。

環境は
Windows2000Pro
MySQL 5.1.14-beta

サンプルのテーブルは
drop table if exists addressbook;
CREATE TABLE addressbook(
id smallint(4) UNSIGNED NOT NULL auto_increment,
name1 varchar(20) default NULL,
birthday date default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=sjis;

INSERT INTO addressbook VALUES
('','名前1','2006-12-22'),
('','','');
で次のエラーが出る。
ERROR 1366 (HY000): Incorrect integer value: '' for column 'id' at row 1

MySQL5.1.14をインストールをしたところ、4.1で動いていたプログラムが軒並みエラーストップ。
どうも、空白を入れるとエラーになるようで、5.1へ移行出来なくて困っています。どなたかご教授をお願いします。

環境は
Windows2000Pro
MySQL 5.1.14-beta

サンプルのテーブルは
drop table if exists addressbook;
CREATE TABLE addressbook(
id smallint(4) UNSIGNED NOT NULL auto_increment,
name1 varchar(20) default NULL,
birthday date default NULL,
PRIMARY KEY (...続きを読む

Aベストアンサー

なるほど、そういう質問でしたか。失礼しました。

調べてみましたけど、ちょっとムリそうでしたねぇ。

エラーの内容からすると、integerに空行はinsertできない旨ですよね。
となると、数値フィールドに''をinsertしたら、NULLと見なすパラメータ等のオプションを探すしかないわけです。
ネットで調べる程度では、わかりませんでした。

QMySQLでデータベースにデータinsert時のエラー。

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column '******' at row 1
とエラーがでて解決できません。どこがおかしいのでしょうか?(JAVA初心者ですいません。)

Aベストアンサー

私の場合ですが、データベース接続直後に
"SET NAMES SJIS;"
を実行すれば正常にINSERT出来ました。

なお、テーブルの作成時に文字コードをSJISにしておく必要があります。私は(cp932 -- SJIS for Windows Japanese)にしました。
後からテーブルの文字コードを修正してもうまくいきませんでした。


人気Q&Aランキング