1

まず、これが私が持っているクエリです:

SELECT 
    COUNT(*) as velocity_count, 
    SUM(`disbursements`.`amount`) as summation_amount 
FROM `disbursements` 
WHERE 
    `disbursements`.`accumulation_hash` = '40ad7f250cf23919bd8cc4619850a40444c5e90c978f88635a09ccf66a82ffb38e39ea51cdfd651b0ebdac5f5ca37cd7a17e0f60fea6cbce1397ccff5fa37346' 
    AND `disbursements`.`caller_id` = 1 
    AND `disbursements`.`active` = 1 
    AND (version_hash != '86b4111677294b27a1805643d193b8d437b6ddb170b4ed5dec39aa89bf070d160cbbcd697dfc1988efea8429b1f1557625bf956180c65d3dcd3a318280e0d2da') 
    AND (`disbursements`.`created_at` BETWEEN '2012-12-15 23:33:22' 
    AND '2013-01-14 23:33:22') LIMIT 1

Explainextendedは次を返します。

+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+
| id | select_type | table         | type  | possible_keys                                                                                                                                 | key                          | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+
|  1 | SIMPLE      | disbursements | range | unique_request_index,index_disbursements_on_caller_id,disbursement_summation_index,disbursement_velocity_index,disbursement_version_out_index | disbursement_summation_index | 1543    | NULL | 191422 |   100.00 | Using where; Using index |
+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+

実際のクエリは約95,000行をカウントします。〜50行に達する別のクエリを説明する場合、説明は同じですが、推定される行が少なくなります。

選択されるインデックスは、accumulation_hash、caller_id、active、version_hash、created_at、amountの順でカバーされます。

COUNT(id)またはCOUNT(caller_id)はnull以外のフィールドであり、count(*)と同じものを返すため、試してみましたが、計画や実行時間には影響しません。実際のクエリの。

これも重い挿入テーブルです。基本的に、すべてのクエリで最後に実行されてから行が挿入または更新されているため、mysqlクエリキャッシュが完全に役立つわけではありません。

memcacheやredisなどを使用してバケット化されたタイムシーケンスキャッシュを作成する前に、これをはるかに高速に動作させるための明らかな解決策はありますか?通常の約50行のクエリは5MSで返され、90k以上の行にまたがるクエリは500〜900MSを使用しており、100MSを超えると実際には何も買う余裕がありません。

日付は、本質的にリアルタイムである必要がある30日間のローリングウィンドウであることを指摘する必要があります。有効期限はおそらく1分程度の粒度で発生する可能性がありますが、コミットするとすぐに新しいアイテムを確認する必要があります。私もRDSを使用しており、Read IOPSは基本的に0であり、CPUは約60〜80%です。巨大な90,000以上のレコードアイテムをクエリしていないとき、CPUは通常10%未満にとどまります。

4

1 に答える 1

0

created_at以前に持っていたインデックスを試すことができますversion_hash(インデックス範囲スキャンを行うとより良いショットが得られる可能性があります...その不等式述語version_hashが計画にどのように影響するかは明確ではありませんが、列の範囲スキャンが無効になっていると思われcreated_atます。

それ以外は、クエリとインデックスは取得しようとしているものとほぼ同じように見えます。EXPLAIN出力は、クエリがインデックスから満たされていることを示しています。

また、特にキーの長さが1543バイトであることを考えると、95,000以上の行を集約していることを考えると、ステートメントのパフォーマンスはそれほど不合理に聞こえません。それは私が通常扱っているよりもはるかに大きいサイズです。

インデックスの列のデータ型は何ですか?また、クラスターキーまたは主キーは何ですか?

accumulation_hash - 128-character representation of 512-bit value
caller_id - integer or numeric (?)
active - integer or numeric (?)
version_hash - another 128-characters
created_at - datetime (8bytes) or timestamp (4bytes)
amount - numeric or integer 

それぞれ1543バイトで95,000行は、140MBのデータのオーダーです。

于 2013-01-15T00:27:11.853 に答える