1

2 つのテーブルからデータを収集し、それらを合計して、ケースの数と合計を表示するクエリを作成しました。

SELECT
    count(ut.id) AS total
    , ( SUM(internal_account) - SUM(( SELECT
            SUM( ub.bill_summs )
        FROM
            u_billing ub
        WHERE
            ub.bill_types = 'correction'
            AND ub.contract_id = ut.contract_id
      )) ) AS summ
FROM  
    u_transactions ut
WHERE
    ut.nulled = 0
    AND ut.type = 'comission'
    AND ut._status = 'not_paid'
    AND DATE( ut.add_timestamp ) = DATE( '2012-05-11' );

しかし、それは本当に遅いです。テストケースでは、次の結果が得られました。

+-------+-------+
| total | summ  |
+-------+-------+
|   182 | 15105 |
+-------+-------+
1 row in set (4.13 sec)

182 ケースで 1 日だけ 4.13 秒ですが、私のライブ サーバーには 60 万ケース以上あるため、これは非常に遅くなります。

パフォーマンスを向上させるためにクエリを書き直す方法はありますか?


再作成されたクエリを使用したソリューション:

DELETE FROM tmpContractSums;
INSERT INTO tmpContractSums
SELECT
    ub.contract_id
    , SUM( ub.bill_summs ) AS bill_summs
FROM
    u_billing ub
WHERE
    ub.bill_types = 'correction'
GROUP BY ub.contract_id;

SELECT
    count(ut.id) AS total
    , ( SUM(internal_account) - SUM(bill_summs) )
FROM  
    u_transactions ut
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id
WHERE
    ut.nulled = 0
    AND ut.type = 'comission'
    AND ut._status = 'not_paid'
    AND ut.add_timestamp BETWEEN '2012-05-11 00:00:00' AND '2012-05-11 23:59:59';

実行時間:500ms

PS: webuser でテーブルを削除できないため、テーブルを作成しました:

CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;

レコードを削除しています。ドロップほど速くはありませんが、それでもオリジナルよりははるかに高速です。

4

4 に答える 4

1

単純に「一時」テーブルを使用するのはどうですか?

DROP TABLE IF EXISTS tmpContractSums;
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;
INSERT INTO tmpContractSums
SELECT
    ub.contract_id
    SUM( ub.bill_summs ) AS bill_summs
FROM
    u_billing ub
WHERE
    ub.bill_types = 'correction'
GROUP BY ub.contract_id;

SELECT
    count(ut.id) AS total
    , ( SUM(internal_account) - COALESCE(bill_summs, 0) )
FROM  
    u_transactions ut
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id
WHERE
    ut.nulled = 0
    AND ut.type = 'comission'
    AND ut._status = 'not_paid'
    AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59';

これはより高速である必要があり、必要に応じて「一時テーブル」にインデックスを追加するか、十分なスペースがある場合は engine=memory を使用してテーブルにすることができます。

または:

DROP TABLE IF EXISTS tmpContractSums;
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;
INSERT INTO tmpContractSums
SELECT
    ub.contract_id
    SUM( ub.bill_summs ) AS bill_summs
FROM
    u_billing ub
WHERE
    ub.bill_types = 'correction'
GROUP BY ub.contract_id;

SELECT
    count(ut.id) AS total
    , ( SUM(internal_account) - (SELECT bill_summs FROM tmpContractSums t WHERE ut.contract_id = t.contract_id ) )
FROM  
    u_transactions ut
WHERE
    ut.nulled = 0
    AND ut.type = 'comission'
    AND ut._status = 'not_paid'
    AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59';
于 2013-02-01T14:20:10.007 に答える
0

ではない?つまり、はるかにうまく機能するはずです。

SELECT
    count(ut.id) AS total
    , SUM(internal_account - COALESCE(ub.b_summs, 0)) summ
FROM u_transactions ut
    LEFT JOIN 
        (
            SELECT 
                contract_id,
                SUM(bill_summs) b_summs
            FROM u_billing
            WHERE bill_types = 'correction'
            GROUP BY contract_id
        ) AS ub
        ON ub.contract_id = ut.contract_id
WHERE
    ut.nulled = 0
    AND ut.type = 'comission'
    AND ut._status = 'not_paid'
    AND DATE( ut.add_timestamp ) = DATE( '2012-05-11' );

また、テーブル列に適用される WHERE 句で関数を使用しないようにする必要があります。インデックスがある場合、関数を使用するとインデックスの使用が許可されません。代わりにこれを使用してください:

AND ut.add_timestamp >= DATE( '2012-05-11' ) AND ut.add_timestamp < DATE( '2012-05-12' );
于 2013-02-01T14:20:53.917 に答える
0

お役に立てれば

    SELECT 
        COUNT(A.id) AS total,
        (SUM(A.internal_account) - SUM(COALESCE(B.bill_sums, 0)) AS 'Sum'
    FROM
    u_transactions A
    LEFT JOIN u_billing B on A.contract_id = B.contract_id
    WHERE 
    A.nulled = 0 AND
    A.type = 'comission' AND
    A._status = 'not_paid' AND
    DATE(A.add_timestamp) = DATE('2012-05-11')
    AND B.bill_types = 'correction';

編集:

サブクエリの結果を合計していることに気づきませんでした。

SELECT
    count(ut.id) AS total
    , ( SUM(internal_account) - **SUM**(( SELECT
            **SUM**( ub.bill_summs )
        FROM
            u_billing ub
        WHERE
            ub.bill_types = 'correction'
            AND ub.contract_id = ut.contract_id
      )) ) AS summ
FROM  
    u_transactions ut

おそらく、合計を合体に置き換えることができます:

-COALESCE(( SELECT
        **SUM**( ub.bill_summs )
    FROM
        u_billing ub
    WHERE
        ub.bill_types = 'correction'
        AND ub.contract_id = ut.contract_id
  ),0)
于 2013-02-01T14:16:18.777 に答える
0

これは物事をスピードアップするはずです:

SELECT 
   COUNT(ua.id) as total,
   SUM(ua.internal_account - ua.corrections) as 'sum'
FROM (  
    SELECT 
       ut.id,
       ut.internal_account,
       SUM(COALESCE(ub.bill_sums, 0)) AS corrections
    FROM
       u_transactions ut
          LEFT JOIN u_billing ub on ut.contract_id = ub.contract_id
    WHERE 
       ut.nulled = 0 AND
       ut.type = 'comission' AND
       ut._status = 'not_paid' AND
       DATE(ub.add_timestamp) = DATE('2012-05-11') AND 
       ut.bill_types = 'correction'
    GROUP BY
       ut.id
    ) as ua

編集:add_timestampテーブルの接頭辞を修正し、欠落を挿入GROUP BY

于 2013-02-01T14:33:32.923 に答える