ここでの問題は、私が持っていた別の質問に関連している...MySQLレコードセットでIDギャップを見つける方法はありますか?
私は数百万レコードを持っており、それらのレコードのそれぞれのIDが自動インクリメントされ、生成された残念ながら、時にはIDは時々そう捨てられID間には多くのギャップがあります。
ギャップを見つけて、放棄されたIDを再利用したいと思います。
MySQLで効率的な方法は何ですか?
ここでの問題は、私が持っていた別の質問に関連している...MySQLレコードセットでIDギャップを見つける方法はありますか?
私は数百万レコードを持っており、それらのレコードのそれぞれのIDが自動インクリメントされ、生成された残念ながら、時にはIDは時々そう捨てられID間には多くのギャップがあります。
ギャップを見つけて、放棄されたIDを再利用したいと思います。
MySQLで効率的な方法は何ですか?
まず、スキップされた値を再利用することでどのようなメリットが得られますか?通常のINT UNSIGNED
は、4,294,967,295まで数えます。 「数百万のレコード」を使用すると、データベースは有効なIDがなくなる前に何千倍も成長する必要があります。 (そして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を入力した後は、いつでもそれを再度実行することができます。
Myタブに整数フィールドの「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;
2番目のクエリ ''選択cs.nはチェスとして、チェンはチェスからセクとして、cs.row = ce.rowのように、実際に存在する大きなギャップを表示するには結合しますが、最初のものはうまくいきます。 – magdmartin
このソリューションは、あなたが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);
あなたがMariaDB
を使用している場合は、より高速なオプションがあり
SELECT * FROM seq_1_to_50000 where seq not in (select col from table);
関連:http://stackoverflow.com/questions/3718229/stop-mysql-reusing-auto-increment-ids –
主キーにINTを使用している場合は、20億件以上のレコードを持つことができます。ギャップを埋めようとするのはどうですか?あなたは番号が不足していますか?私は、数字がレコードが追加された順番に対応していることを知ることに利点があることが分かりました。 – minboost
非常に大きなテーブルのIDを再利用しようとするよりも、プライマリキーのタイプをBIGINT(INTが提供する4つの金額が短すぎる場合)に変更すると、パフォーマンスが低下することがあります。 –