1

現在、次のストアド プロシージャを実行しています。元の手順よりもはるかに効率的ですが、それでもまだ時間がかかりすぎています。最初の 10k から 30k のレコードが高速に発生したため、スローダウンが何であるかは実際にはわかりませんが、さらに遅くなるにつれて遅くなりました。約 170 万行の約 250k 行を更新する予定です。これが完了したら、同様のことを行って、各「太陽系」にレコードを挿入します。

これにかかる時間の例を挙げます。現在、24 時間強実行されており、1716 回の反復のうち 786 回しか実行されていません。選択の制限を変更する理由は、テーブルのセクターごとに 1000 行が可能であるためです。個人的に速度低下は見られませんが、MySQL の内部の仕組みがよくわかりません。

この作業は私のローカル コンピューターで行われています。遅くはありませんが、これらのクエリをより効率的にするためにサーバー レベルで変更を行う必要がある可能性は常にあります。必要に応じて、サーバーの設定を変更できるので、それも可能です。参考までに、Windows 7 で MySQL のストック構成を使用しています。

DECLARE CurrentOffset int; -- Current offset limit to only deal with one 
DECLARE CurrentOffsetMultiplier int;
DECLARE RandRow int; -- Random Row to make a Solar System with
DECLARE CheckSystemExists int; -- Used to insure RandRow is not already a Solar System Row
DECLARE TotalSystemLoops int; -- Total number of loops so each Galaxy gets it's systems.
DECLARE RandomSolarSystemCount int; -- This is the number of Solar Systems that will be in each Galaxy;
DECLARE UpdateSolarCount int;
DECLARE NumberOfOffsets int;

SET CurrentOffsetMultiplier = 0;
SET NumberOfOffsets = 1716;
SET CurrentOffset = 0;


OffsetLoop: LOOP
        SET UpdateSolarCount = 0;
        /*Sets the amount of Solary Systems going in a Galaxy*/
            CheckRandomSolarSystemCount: LOOP
                SET RandomSolarSystemCount = FLOOR(125 + RAND() * (175 - 125) + 1);  
                IF RandomSolarSystemCount >= 125 THEN
                    IF RandomSolarSystemCount <= 175 THEN
                        LEAVE CheckRandomSolarSystemCount;
                    END IF;
                END IF;
            END LOOP;
        UpdateGalaxyWithSolarSystems: LOOP
                SET UpdateSolarCount = UpdateSolarCount + 1;
                IF UpdateSolarCount > RandomSolarSystemCount THEN
                    LEAVE UpdateGalaxyWithSolarSystems;
                END IF;
                        /*Sets RandRow and CheckSystemExists*/
                        CheckExistsLoop: Loop
                            SET RandRow = FLOOR(0 + RAND() * (1000)+ 1);
                            SET CheckSystemExists = (SELECT COUNT(*)
                                FROM
                                    (SELECT * FROM
                                        (SELECT * FROM galaxies2 LIMIT CurrentOffset, 1000) AS LimitedTable
                                    LIMIT RandRow ,1) AS RandTable
                                WHERE SolarSystemName IS NULL);
                            IF CheckSystemExists THEN
                                LEAVE CheckExistsLoop;
                            END IF;
                        END LOOP;

                        /*Updates the tables SolarSystemName column with a default system name*/
                        UPDATE galaxies2 
                            SET SolarSystemName = CONCAT("Solar System ", RandRow)
                            WHERE galaxies2.idGalaxy = 
                                (SELECT LimitedTable.idGalaxy AS GalaxyID FROM
                                    (SELECT galaxies2.idGalaxy FROM galaxies2 LIMIT CurrentOffset, 1000) AS LimitedTable
                                LIMIT RandRow ,1)
                        ;
        END LOOP;
        SET CurrentOffsetMultiplier = CurrentOffsetMultiplier + 1;
        SET CurrentOffset = CurrentOffsetMultiplier * 1000;
        IF CurrentOffsetMultiplier = 1717 THEN
            LEAVE OffsetLoop;
        END IF;
END LOOP;
4

1 に答える 1

0

galaxies2 テーブルを「歩いている」ため、ますます遅くなります。

SELECT * FROM galaxies2 LIMIT CurrentOffset, 1000

CurrentOffset 値が増加するにつれて、MySQL はより多くのレコードを「ウォーク」して開始点に到達する必要があります。主キーに ORDER BY を指定すると、実際には速度が向上する場合があります。順序が指定されていない場合、MySQL はレコードをランダムに読み取るだけなので、とにかく ORDER BY が必要です。特定の順序でレコードを読み取るわけではないため、(可能性は低いですが) 異なるオフセットで同じレコードのセットを取得できます。

自動インクリメント フィールドで範囲を指定する方がよいでしょう。あなたが持っていると仮定します。次に、最初と最後のクエリはほぼ同じように実行する必要があります。削除されたレコードからのギャップがある可能性があるため、理想的ではありません。

SELECT * FROM galaxies2 WHERE auto_incr_field BETWEEN CurrentOffset AND CurrentOffset+1000
于 2013-02-01T14:50:23.553 に答える