0

私は奇妙なものを持っています。それが私の構文 (単純に見える) なのか、バグなのか (またはサポートされていないだけなのか) はわかりません。

動作するが不必要に遅いクエリは次のとおりです。

UPDATE table1 
    SET table1column1 = 
        (SELECT COUNT(DISTINCT table2column1) FROM table2view WHERE table2column1 <= (SELECT table2column1 FROM table2 WHERE table2.id = table1.id) )
        / 
        (SELECT COUNT(DISTINCT table2column1) FROM table2) 

       + (SELECT COUNT(DISTINCT table2column2) FROM table2view WHERE table2column2 <= (SELECT table2column2 FROM table2 WHERE table2.id = table1.id) ) 
        / 
        (SELECT COUNT(DISTINCT table2column2) FROM table2) 

       + (SELECT COUNT(DISTINCT table2column3) FROM table2view WHERE table2column3 <= (SELECT table2column3 FROM table2 WHERE table2.id = table1.id) ) 
        / (SELECT COUNT(DISTINCT table2column3) FROM table2);

これは、重複を除いた 3 つのパーセンタイル (table2column1、table2column2、および table2column3) の合計です。

ここが変なところです。これがサブクエリで動作するようにするには、ビューを使用する必要があります。そうしないと、 の最初の行WHEREのみが表示され、残りの行が に設定されます。の正確な複製です。ええ、奇妙です。UPDATEtable1table1column10table2viewtable2

を使用しない場合はDISTINCT、ビューなしで実行できます。それは理にかなっていますか? 注:DISTINCT重複が多いため、持っている必要があります。

ビューからのみ作成しようとしましSELECTたが、速度がさらに低下しました。

問題の内容と、このクエリを作り直してそれほど時間がかからないようにする最善の方法を知っている人はいますか? にTRIGGERあり、更新されたデータはかなりオンデマンドです。

よろしくお願いします!

詳細

phpMyAdmin のコマンド ラインで速度をテストしています。

ビューが多く、実際に使用するテーブルが少ないほど、速度が低下するため、ビューが劣化していると確信しています。

なしDISTINCTで行うと、超高速です。

ビューでのみ機能しますか?

のコピーをセットアップしましたtable2。最初に、ビューをコピーに置き換えて元のクエリを実行しようとしました。立ち入り禁止。

ビューの代わりにコピーを使用して、以下のクエリを実行しようとしました。立ち入り禁止。

これらの定数の導入により、私がやろうとしていることをよりよく示すことができれば幸いです。

SET @table2column1_distinct_count = (SELECT COUNT(DISTINCT table2column1) FROM table2);
SET @table2column2_distinct_count = (SELECT COUNT(DISTINCT table2column2) FROM table2);
SET @table2column3_distinct_count = (SELECT COUNT(DISTINCT table2column3) FROM table2);
UPDATE table1, table2
    SET table1.table1column1 = (SELECT COUNT(DISTINCT table2column1) FROM  table2view WHERE table2column1 <= table2.table2column1) / @table2column1_distinct_count 
    + (SELECT COUNT(DISTINCT table2column2) FROM  table2view WHERE table2column2 <= table2.table2column2) / @table2column2_distinct_count 
    + (SELECT COUNT(DISTINCT table2column3) FROM  table2view WHERE table2column3 <= table2.table2column3) / @table2column3_distinct_count 
        WHERE table1.id = table2.id;

繰り返しますtable2が、の代わりに使用するtable2viewと、最初の行のみが適切に更新され、他のすべての行の table1.table1column1 = が設定されます0

算数

= を、、およびbytable1.table1column1のパーセンタイルの合計に設定しようとしています。table2column1table2column2table2column3id

( a table2columnX<= の個別の値を現在の までカウントする ) / (個別の s のtable2columnX合計数)によってパーセンタイルを計算します。table2columnX

DISTINCT過剰な重複を取り除くために使用します。

意見

これがビューのSELECTです。これは役に立ちますか?

CREATE VIEW myTable.table2view AS SELECT
    table2.table2column1 AS table2column1,
    table2.table2column2 AS table2column2,
    table2.table2column2 AS table2column3,
FROM table2
GROUP BY table2.id;

GROUP BYこの作業を行うビューの中に何か特別なものがありますかSELECT(それは私には見えません)?

4

1 に答える 1

0

トリガーが起動したときにテーブルに繰り返しアクセスしているため、クエリが遅いと言えます。

私は SQL の専門家ではありませんが、一時テーブルを使用してクエリをまとめようとしました。クエリの高速化に役立つかどうかを確認できます。以下のコード サンプルでは、​​異なるが似ている列名を使用しています。

編集:以前のコードに計算エラーがありました。今更新しました。

SELECT COUNT(id) INTO @no_of_attempts from tb2;

-- DROP TABLE IF EXISTS S1Percentiles;
-- DROP TABLE IF EXISTS S2Percentiles;
-- DROP TABLE IF EXISTS S3Percentiles;

CREATE TEMPORARY TABLE S1Percentiles (
    s1 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);

CREATE TEMPORARY TABLE S2Percentiles (
    s2 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);

CREATE TEMPORARY TABLE S3Percentiles (
    s3 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);



INSERT INTO S1Percentiles (s1, percentile)
    SELECT A.s1, ((COUNT(B.s1)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s1 from tb2) A
    INNER JOIN tb2 B
    ON B.s1 <= A.s1
    GROUP BY A.s1;

INSERT INTO S2Percentiles (s2, percentile)
    SELECT A.s2, ((COUNT(B.s2)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s2 from tb2) A
    INNER JOIN tb2 B
    ON B.s2 <= A.s2
    GROUP BY A.s2;

INSERT INTO S3Percentiles (s3, percentile)
    SELECT A.s3, ((COUNT(B.s3)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s3 from tb2) A
    INNER JOIN tb2 B
    ON B.s3 <= A.s3
    GROUP BY A.s3;

-- select * from S1Percentiles;
-- select * from S2Percentiles;
-- select * from S3Percentiles;

UPDATE tb1 A
    INNER JOIN
    (
    SELECT B.tb1_id AS id, (C.percentile + D.percentile + E.percentile) AS sum FROM tb2 B
        INNER JOIN S1Percentiles C
        ON B.s1 = C.s1
        INNER JOIN S2Percentiles D
        ON B.s2 = D.s2
        INNER JOIN S3Percentiles E
        ON B.s3 = E.s3
    ) F
    ON A.id = F.id

    SET A.sum = F.sum;

-- SELECT * FROM tb1;

DROP TABLE S1Percentiles;
DROP TABLE S2Percentiles;
DROP TABLE S3Percentiles;

これが何をするかというと、各スコア グループのパーセンタイルを記録し、最後tb1に各生徒の行のパーセンタイルを再計算する代わりに、必要なデータで列を更新するだけです。

また、これらの列に対するクエリを最適化するために、列s1にインデックスを付ける必要があります。s2s3

注: データベース スキーマに従って列名を更新してください。100また、パーセンタイルは通常そのように計算されると思われるため、各パーセンタイルの計算には が掛けられていることに注意してください。

于 2012-12-31T06:51:11.753 に答える