2016-10-31 6 views
0

私は、1000万レコードを持つMySqlデータベースでイベントと呼ばれる大きなテーブルを持っています。小さいテーブルでインデックスを持つ大きなテーブルに結合する

イベント

CREATE TABLE `event` (
    `eventId` BIGINT(20) NOT NULL AUTO_INCREMENT, 
    `eventTime` BIGINT(20) NOT NULL COMMENT 'ex: 1431201865000 (epoch is milliseconds)', 
    `sourceId` BIGINT(20) NOT NULL COMMENT 'ex: pole-code: 1 = JA005, patrolCarCode: 5000 = D4588', 
    PRIMARY KEY (`eventId`), 
    INDEX `eventTime` (`eventTime`), 
    INDEX `sourceId` (`sourceId`) 
) 
COLLATE='utf8_unicode_ci' 
ENGINE=InnoDB 
AUTO_INCREMENT=12343262; 

私は約70の記録を持つ小さなテーブルを持っています。

ソース

CREATE TABLE `source` (
    `sourceId` BIGINT(20) NOT NULL AUTO_INCREMENT, 
    `sourceName` VARCHAR(100) NOT NULL COMMENT 'ex: pole-code: JA005, patrolCarCode:D4588' COLLATE 'utf8_unicode_ci', 
    `sourceGps` VARCHAR(40) NULL DEFAULT NULL COMMENT 'Only for Fixed source (Poles) ex: 25.110227 N 55.239798 E, 24.993183 N 55.250382 E, 0.000000 N 0.000000 E' COLLATE 'utf8_unicode_ci', 
    `sourceAddress` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Only for Fixed source (Poles) ex: Dubai, Bur Dubai, Burjman Center Interchange' COLLATE 'utf8_unicode_ci', 
    `sourceAltAddress` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Alternative address, ex: address in arabic' COLLATE 'utf8_unicode_ci', 
    PRIMARY KEY (`sourceId`), 
    INDEX `sourceName` (`sourceName`) 
) 
COLLATE='utf8_unicode_ci' 
ENGINE=InnoDB 
AUTO_INCREMENT=71 
; 

データ

INSERT INTO `event` (`eventId`, `eventTime`, `sourceId`) VALUES 
    (1474261476616, 33, 1), 
    (1474261438966, 26, 2), 
    (1474261479346, 25, 3), 
    (1474261429952, 8, 5), 
    (1474261477316, 33, 6) 

INSERT INTO `source` (`sourceId`, `sourceName`, `sourceGps`, `sourceAddress`) VALUES 
    (1, 'JA001', '25.110227 N 55.239798 E', 'Interchange'), 
    (2, 'JA002', '25.110227 N 55.239798 E', 'Interchange'), 
    (3, 'JA003', '25.110227 N 55.239798 E', 'Interchange'), 
    (4, 'JA004', '25.110227 N 55.239798 E', 'Interchange'), 
    (5, 'JA005', '25.110227 N 55.239798 E', 'Interchange') 

タスク

私は '1474261429952' を言って、特定の時間の後に起こったすべてのイベントを取得したいです。

検索の結果、これまでのところ以下のようなクエリが導出されていますが、結果は出ますが速度は非常に遅いです。 テーブルから結果を取得するのに約1.5分かかります。

SELECT count(source.sourceId) as 'totalEvents', source.sourceId, source.sourceGps, 
source.sourceAddress from event inner join source on event.sourceId = source.sourceId 
where eventTime >= 1474261429952 group by source.sourceId 

結果を説明:

Here is explain result

は、私はそれをスピードアップすることができますどのように私を導いてください。

ありがとうございました。

+2

は、あなたがそのが遅く場所を確認するためにクエリをプロファイリングしようとしたことがありますか? – arijeet

+1

Plsにはあなたの質問に 'explain'の結果が含まれています。 – Shadow

+0

Event.EventTimeまたはevent.sourceIDを数えると、より速く実行できると思うイベントでインデックスを使用できるようです。クエリの説明は簡単になります。 – xQbert

答えて

0

フィールドsourceid, eventtime(この特定の順序で)をカバーするeventsテーブルに複数列のインデックスを追加する必要があります。

理由:MySQLはクエリでテーブルごとに1つのインデックスを使用できます(インデックスマージは小さな例外です)。 sourceid, eventtimeフィールドには別々のインデックスがありますが、MySQLでは使用すると考えていますが、これらのフィールドは却下されます(説明結果のキーとキーフィールドを参照)。

インデックスが作成された後、別のexplainでインデックスの使用状況を確認してください。 analyse tableが役立つかもしれませんが、新しいインデックスを使用するには、インデックスヒント(use indexまたはforce index)を使用する必要があります。

+0

私はそれを試してみましょう。 –

0

複数のフィールドインデックスと個人の問題を指摘していますが、(sourceid、eventtime)ではなく、(eventtime、sourceid)の異なる順序をお勧めします。理由は...あなたのデータが10歳の場合は、古いものから最新のものまですべてのソースを調べなければなりません。問題の現在の日付範囲にジャンプするのではなく、また、EVENTではなくSOURCEテーブルでグループ化するのではなく、イベントのインデックスを利用しています。なぜなら、キーはいつでも同じであるからです。

ソースは、あなたが(ソースID、イベント時刻)に基づいてインデックスを持つ試してみたいならば、私は、クエリを変更し、第一の位置にソーステーブルを置き、と書きます

SELECT 
     count(*) as 'totalEvents', 
     source.sourceId, 
     source.sourceGps, 
     source.sourceAddress 
    from 
     event 
     inner join source 
      on event.sourceId = source.sourceId 
    where 
     eventTime >= 1474261429952 
    group by 
     event.sourceId 

ですので。 ..あなたが戻ってくるパフォーマンスの違いが面白いでしょう。

SELECT 
     S.sourceId, 
     S.sourceGps, 
     S.sourceAddress, 
     count(*) as totalEvents 
    from 
     source S 
     join event E 
      on S.sourceId = E.sourceId 
      AND E.eventTime >= 1474261429952 
    group by 
     S.sourceId 
+0

それほど大きな違いはありませんでした。 5秒しか保存されませんでした。 –

関連する問題