2016-07-05 10 views
0

私は約10のテーブルのUNION ALL句からビューを作成し、その上に日付範囲でいくつかの検索クエリを適用したいとします。しかし、レコード数が増えると、クエリを実行するのに時間がかかります。現在、ビューには20億行があります。MySQLのテーブルのようにビューを分割することはできますか?

CREATE TABLE IF NOT EXISTS `tbl_queue_stats_0716` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `server_id` int(11) NOT NULL, 
    `uniqueid` varchar(100) DEFAULT NULL, 
    `queue_datetime` datetime NOT NULL, 
    `queue_timestamp` varchar(100) NULL, 
    `qname_id` int(11) NOT NULL, 
    `qagent_id` int(11) NOT NULL, 
    `qevent_id` int(11) NOT NULL, 
    `info1` varchar(100) DEFAULT NULL, 
    `info2` varchar(100) DEFAULT NULL, 
    `info3` varchar(100) DEFAULT NULL, 
    `info4` varchar(100) DEFAULT NULL, 
    `info5` varchar(100) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
); 

の表は、月次ベースで作成されているので、

... tbl_queue_stats_0616、tbl_queue_stats_0516、tbl_queue_stats_0416のようなテーブルがあることができ、私は複数の検索クエリを適用したい:

表構造が似ています2か月以上の検索に日付範囲が必要な場合はテーブル私は分割ビューを介した検索が速く私のクエリを実行することができると思い

select server_id,server_name,queue_id,queue_name,qevent_id,event, 
     count(id) as cnt,sum(info1) as info1, sum(info2) as info2, 
     sum(info3) as info3, sum(info4) as info4, sum(info5) as info5, 
     max(cast(info2 AS SIGNED)) as max_info2, 
     max(cast(info3 AS SIGNED)) as max_info3 
    from 
     (SELECT a.server_id as server_id,e.server_name as server_name, 
       a.id,a.`queue_datetime`, b.agent, a.qname_id as queue_id , 
       c.queue as queue_name,d.event,a.qevent_id,a.info1,a.info2, 
       a.info3,a.info4,a.info5 
      FROM view_queue_stats a,tbl_qagent b, tbl_qname c, tbl_qevent d, 
       tbl_server e 
      WHERE a.qagent_id=b.id 
       AND a.qname_id=c.id 
       AND a.qevent_id=d.id 
       AND a.server_id=e.id 
       AND DATE(a.queue_datetime) between '" . $start_date . 
              "' AND '" . $end_date . "' 
       AND a.server_id IN ($server_name) 
    )as total 
    GROUP BY qevent_id,queue_id,server_id 
    ORDER BY length(server_name), server_name,queue_id,qevent_id. 

検索クエリは次のようになります。これを実現するために、パーティション関連のパラメータを適用してビューを作成しましたが、成功しませんでした。

以下は、SHOW CREATE VIEW view_queue_statsの出力です。

CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER 
     VIEW `view_queue_stats` 
     AS select `tbl_queue_stats_0116`.`id` AS `id`, 
     `tbl_queue_stats_0116`.`server_id` AS `server_id`, 
     `tbl_queue_stats_0116`.`uniqueid` AS `uniqueid`, 
     `tbl_queue_stats_0116`.`queue_datetime` AS `queue_datetime`, 
     `tbl_queue_stats_0116`.`queue_timestamp` AS `queue_timestamp`, 
     `tbl_queue_stats_0116`.`qname_id` AS `qname_id`, 
     `tbl_queue_stats_0116`.`qagent_id` AS `qagent_id`, 
     `tbl_queue_stats_0116`.`qevent_id` AS `qevent_id`, 
     `tbl_queue_stats_0116`.`info1` AS `info1`, 
     `tbl_queue_stats_0116`.`info2` AS `info2`, 
     `tbl_queue_stats_0116`.`info3` AS `info3`, 
     `tbl_queue_stats_0116`.`info4` AS `info4`, 
     `tbl_queue_stats_0116`.`info5` AS `info5` 
    from `tbl_queue_stats_0116` 
    union all 
select `tbl_queue_stats_0216`.`id` AS `id`, 
     `tbl_queue_stats_0216`.`server_id` AS `server_id`, 
     `tbl_queue_stats_0216`.`uniqueid` AS `uniqueid`, 
     `tbl_queue_stats_0216`.`queue_datetime` AS `queue_datetime`, 
     `tbl_queue_stats_0216`.`queue_timestamp` AS `queue_timestamp`, 
     `tbl_queue_stats_0216`.`qname_id` AS `qname_id`, 
     `tbl_queue_stats_0216`.`qagent_id` AS `qagent_id`, 
     `tbl_queue_stats_0216`.`qevent_id` AS `qevent_id`, 
     `tbl_queue_stats_0216`.`info1` AS `info1`, 
     `tbl_queue_stats_0216`.`info2` AS `info2`, 
     `tbl_queue_stats_0216`.`info3` AS `info3`, 
     `tbl_queue_stats_0216`.`info4` AS `info4`, 
     `tbl_queue_stats_0216`.`info5` AS `info5` 
    from `tbl_queue_stats_0216` 
    union all 
    ... 

| utf8     | utf8_general_ci  | 

ビューを分割する方法はありますか?

+0

テーブルはどのようなENGINEですか? –

+0

なぜ手動でデータを数か月に分割しましたか?パフォーマンス(おそらく得られなかったでしょうか?)利便性(あなたは不平を言っていますか?)その他? –

+0

ENGINEはすべてのテーブルのInnoDBです。 1つのテーブルに数百万のレコードがあるので、私は月ごとにすべてのテーブルを分割しました。すべてのデータに対して1つのテーブルを作成すると、テーブルが網羅的になります。これに代わる方法はありますか? – Dhruten

答えて

0

チェック.That下記のリンクはあなた

http://dev.mysql.com/doc/refman/5.5/en/partitioning.html

+0

テーブル分割は非常にうまく説明されていますが、私の問題には何も役に立たないことがあります。 – Dhruten

+0

ええ、パーティション分割はめったに解決策ではありません。 SHOW CREATE TABLEとそのクエリを提供してください。私はもっ​​と建設的なことを言うかもしれません。 –

+0

@RickJames pls編集した質問をチェックします。 – Dhruten

1

あなたは億server_idsを持つことになります助けるかもしれませんか?おそらく、MEDIUMINT UNSIGNEDのように、3バイト(4ではなく)と16Mの制限のような、より小さいintを使うことができます。他のIDの場合は同上。 (より小さい - >キャッシュ可能 - > I/O - >少ない)

queue_timestampはタイムスタンプですか?もしそうなら、なぜVARCHAR

cast(info2 AS SIGNED) - あなたは前がそれを挿入し、データをクレンジングし、適切なデータ型を(?INT)を使用したほうが良いでしょう。

重要:機能内の列を非表示にしないでください(DATE(a.queue_datetime))。インデックスの使用を禁止します。下記参照。

ほとんどのフィールドは実際にはオプションですか?そうでない場合はNULLの代わりにNOT NULLとします。

重要:戻る質問へ ... 10のテーブルのUNION ALLには、「パーティション・プルーニングは」起こり得ないPARTITIONedテーブルに似て実行します。しかし、UNIONは、すべてのデータを含む一時テーブルを生成してからフィルタリングを開始するように見えるため、悪化する可能性があります。クエリにはEXPLAIN SELECT ...を入力してください。

重要:INDEX(server_id, queue_datetime)は、パフォーマンスに役立つ可能性があります。これは、この仮定を確認または拒否する必要があります。

ここで問題は、「プルーニング」が発生するかどうかです。考えられるケースは、query_datetimeが結果をいくつかのパーティションに限定する場合です。テーブルはquery_datetimeに基づいていますか? SELECTsは通常1つまたは2つのテーブルに限定されていますか?これにVIEWから変更すると大幅に役立ちます、その後、上記に正しい答えを考えると、変更が提案与え

PARTITION BY RANGE(TO_DAYS(query_datetime)) ... 

しかし、それは結局のところ、パーティショニングは本当に必要はありません。上記のINDEXWHEREへの変更と共に)は、テーブルでも同様に機能します。

しかし、もう少し質問があります。あなたは1つを言ったSELECT;他にはありますか? 1つのクエリのクエリ/スキーマを修正することは、他のクエリに役立つかもしれません。あなたは "古い"テーブル/パーティションを削除しますか?もしそうなら、パーティション化はうまくいくでしょう。

これらの問題に答えると、途中で補正を行うことができます。

関連する問題