2011-06-30 17 views
2

私はこのようなテーブルを持っています。mySQLクエリの速度を向上させる

CREATE TABLE `accounthistory` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `date` datetime DEFAULT NULL, 
    `change_ammount` float DEFAULT NULL, 
    `account_id` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
) 

アカウントの毎日の請求の一覧です。私が使用しているアカウントの残高が必要な場合 SELECT sum(change_ammount)FROM accounthistory WHERE account_id =; account_id列にインデックスを追加したのでかなり速くなりました。

SELECT main.date as date from accounthistory as main 
WHERE main.account_id=484368430 
     AND (SELECT sum(change_ammount) FROM accounthistory as sub 
          WHERE sub.account_id=484368430 AND 
           sub.date < main.date)<0 
ORDER BY main.date DESC 
LIMIT 1; 

しかし、それは非常に遅い動作します:アカウントがマイナスに(日付をSUM(change_ammount)< 0時)に行ったとき が、私はこのクエリを使用し

は、しかし、今、私は時間を見つける必要があります。あなたはより良い解決策を提案できますか? (account_idだけでなく)インデックスが必要なのでしょうか?

答えて

0
SELECT MAX(main.date) as date 
from accounthistory as main 
WHERE main.account_id=484368430 
     AND EXISTS (SELECT 1 FROM accounthistory as sub 
          WHERE sub.account_id=main.account_id AND 
           sub.date < main.date HAVING SUM(sub.change_ammount) < 0) 
1

クエリを高速化する方法は、denormalizationを使用することです。現在の勘定残高をすべてのレコードに保存します。これを達成するため、次の3つのことを行う必要があり、その後、我々は、クエリがどのように見えるかを見ていきましょう:

a)をあなたのテーブルに列を追加します。

ALTER TABLE accounthistory ADD balance float; 

B)新しいの移入しますコラム

UPDATE accounthistory main SET 
balance = (
    SELECT SUM(change_amount) 
    FROM accounthistory 
    where account_id = main.account_id 
    and data <= main.date 
); 

C)は、a)、b)は、アプリケーション・ロジックを使用してトリガを使用またはc)UPDATE ... WHERE id = ?

すなわち、それを追加した後に追加された行のための上記 UPDATEのステートメントを実行し、新しい行を移入します210

アカウントが負に変更されたデータを見つけるためのクエリは、次のようになります。

SELECT date 
from accounthistory 
where balance < 0 
and balance - change_amount > 0 
and account_id = ?; 
+0

ありがとうございました。私は非正規化を試みます。 – Taras

関連する問題