5

ここでの問題は、私が持っていた別の質問に関連しています...

私は何百万ものレコードを持っていますが、それらの各レコードのIDは自動的にインクリメントされますが、残念ながら、生成されたIDが破棄されることがあるため、ID間には多くのギャップがあります。

ギャップを見つけて、放棄されたIDを再利用したいと思います。

MySQLでこれを行うための効率的な方法は何ですか?

4

4 に答える 4

17

まず、スキップされた値を再利用することでどのような利点を得ようとしていますか?普通INT UNSIGNEDなら4,294,967,295まで数えることができます。「数百万のレコード」を使用すると、有効なIDがなくなる前に、データベースを1000倍に増やす必要があります。(そして、を使用するBIGINT UNSIGNEDと、最大18,446,744,073,709,551,615の値になります。)

MySQLがスキップした値をリサイクルしようとすると、そもそもMySQLを実際に気にしない何かを補うために多くの時間を費やす可能性があります。

そうは言っても、次のような欠落しているIDを見つけることができます。

SELECT id + 1
FROM the_table
WHERE NOT EXISTS (SELECT 1 FROM the_table t2 WHERE t2.id = the_table.id + 1);

これにより、各シーケンスで最初に欠落している番号のみが検出されます(たとえば、{1, 2, 3, 8, 10}検出される場合{4,9})が、効率的である可能性が高く、もちろん、IDを入力すると、いつでも再度実行できます。

于 2011-12-09T18:07:43.257 に答える
2

以下は、mytabの整数フィールド「n」の各ギャップの行を返します。

/* cs will contain 1 row for each contiguous sequence of integers in mytab.n
   and will have the start of that chain.
   ce will contain the end of that chain */
create temporary table cs (row int auto_increment primary key, n int);
create temporary table ce like cs;
insert into cs (n) select n from mytab where n-1 not in (select n from mytab) order by n;
insert into ce (n) select n from mytab where n+1 not in (select n from mytab) order by n;
select ce.n + 1 as bgap, cs.n - 1 as egap
  from cs, ce where cs.row = ce.row + 1;

ギャップの代わりに連続チェーンが必要な場合、最終的な選択は次のようになります。

select cs.n as bchain, ce.n as echain from cs,ce where cs.row=ce.row;
于 2012-12-30T17:52:35.950 に答える
1

最初の要素を1として含める必要がある場合は、このソリューションの方が適しています。

SELECT
    1 AS gap_start,
    MIN(e.id) - 1 AS gap_end
FROM
    factura_entrada e
WHERE
    NOT EXISTS(
        SELECT
            1
        FROM
            factura_entrada
        WHERE
            id = 1
    )
LIMIT 1
UNION
    SELECT
        a.id + 1 AS gap_start,
        MIN(b.id)- 1 AS gap_end
    FROM
        factura_entrada AS a,
        factura_entrada AS b
    WHERE
        a.id < b.id
    GROUP BY
        a.id
    HAVING
        gap_start < MIN(b.id);
于 2013-06-17T13:26:55.747 に答える
0

を使用しているMariaDB場合は、より高速なオプションがあります

SELECT * FROM seq_1_to_50000 where seq not in (select col from table);

ドキュメント:https ://mariadb.com/kb/en/mariadb/sequence/

于 2017-01-10T14:33:50.660 に答える