1. 概要:
私たちのデータベース設計において、主キーは不可欠であり、主キーの設計はデータベース全体の設計に大きな影響を与えます。 自動増分フィールドとGuidフィールドのパフォーマンスを比較しますので、ぜひ議論してください。
2. はじめに:
1. 自己増分場
自己増分フィールドは毎回順番に増分され、テーブル内の主キーが繰り返されないようにします。 自己増量フィールドタイプの最大値を超えて一から増分しない限り、これはほぼ不可能です。 自己増量フィールドを主キーとして使うのは非常に簡単で、通常はテーブル作成時に自己増量属性を宣言するだけです。
自己増分値はシステム上で維持すべきすべてのグローバルデータ値であり、データが挿入されるたびに値が増加します。 同時環境で同等のものが一意アイデンティティを生成する場合、各インクリメンタル値はこのグローバル値でロックされ、アンロックされなければインクリメントの一意性が保たれません。 これは同時にボトルネックとなり、パフォーマンスの問題も伴います。
データの移行やインポート時に自己増分フィールドが重複することがあり、これは間違いなく悪夢のような問題です(私もすでに経験しています)。
分散型データベースを構築したい場合、この自己増分フィールドは問題となります。 これは分散型データベースでは、異なるデータベースの同じ名前のテーブルを同期複製する必要があるためです。 データベーステーブルの自己増分値は、同じテーブルの自己増分価値と他のデータベースで重複する可能性が高いです。
2. ユニーク識別子(Guid)フィールド
MS SQLデータベースでは、テーブル構造はフィールドタイプをuniqueidentifierとして指定することで作成でき、そのデフォルト値はNewID()を使って一意Guid(Globally Unique Identifier)を生成できます。
Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.
GUIDの利点は、生成されたIDが比較的一意であることであり、データのエクスポートでも段階的な開発でも問題が起きないことです。 しかし、生成されるIDは比較的長く、データベースの容量も占有されているため、外部ストレージの価格が下がるため、この点を考慮する必要はありません。 さらに、Guidは記憶しやすく、この点で自動増分フィールドほど優れていません。自動増分フィールドはプログラムのデバッグ時にあまり便利ではありません。
3. テスト:
1. 環境のテスト
オペレーティングシステム:Windows Server 2003 R2 エンタープライズエディションサービスパック2
データベース:MS SQL 2005
CPU:Intel(R) Pentium(R) 4 CPU 3.40GHz
メモリ:DDRII。667 1G
ハードドライブ:WD 80G
2. データベーススクリプト
- --自增量字段表
- CREATE TABLE [dbo].[Table_Id](
- [Id] [int] IDENTITY(1,1) NOT NULL,
- [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
- CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED
- (
- [Id] ASC
- )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
- --Guid字段表
- CREATE TABLE [dbo].[Table_Guid](
- [Guid] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Table_Guid_Guid] DEFAULT (newid()),
- [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
- CONSTRAINT [PK_Table_Guid] PRIMARY KEY CLUSTERED
- (
- [Guid] ASC
- )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
コードをコピーします テストコード
- 1using System;
- 2using System.Collections.Generic;
- 3using System.Text;
- 4using System.Data.SqlClient;
- 5using System.Diagnostics;
- 6using System.Data;
- 8namespace GuidTest
- 9{
- class Program
- {
- string Connnection = "server=.;database=GuidTest;Integrated Security=true;";
- static void Main(string[] args)
- {
- Program app = new Program();
- int Count = 10000;
- Console.WriteLine("数据记录数为{0}",Count);
- //自动id增长测试;
- Stopwatch WatchId = new Stopwatch();
- Console.WriteLine("自动增长id测试");
- Console.WriteLine("开始测试");
- WatchId.Start();
- Console.WriteLine("测试中");
- 25 app.Id_InsertTest(Count);
- //app.Id_ReadToTable(Count);
- //app.Id_Count();
- 29 //查询第300000条记录;
- //app.Id_SelectById();
- 32 WatchId.Stop();
- Console.WriteLine("时间为{0}毫秒",WatchId.ElapsedMilliseconds);
- Console.WriteLine("测试结束");
- 36 Console.WriteLine("-----------------------------------------");
- //Guid测试;
- Console.WriteLine("Guid测试");
- Stopwatch WatchGuid = new Stopwatch();
- Console.WriteLine("开始测试");
- WatchGuid.Start();
- Console.WriteLine("测试中");
- 44 app.Guid_InsertTest(Count);
- //app.Guid_ReadToTable(Count);
- //app.Guid_Count();
- 48 //查询第300000条记录;
- //app.Guid_SelectById();
- 51 WatchGuid.Stop();
- Console.WriteLine("时间为{0}毫秒", WatchGuid.ElapsedMilliseconds);
- Console.WriteLine("测试结束");
- Console.Read();
- }
- 57 /**////
- /// 自动增长id测试
- ///
- private void Id_InsertTest(int count)
- {
- string InsertSql="insert into Table_Id ([Value]) values ({0})";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- conn.Open();
- SqlCommand com = new SqlCommand();
- for (int i = 0; i < count; i++)
- {
- com.Connection = conn;
- com.CommandText = string.Format(InsertSql, i);
- com.ExecuteNonQuery();
- }
- }
- }
- 76 /**////
- /// 将数据读到Table
- ///
- private void Id_ReadToTable(int count)
- {
- string ReadSql = "select top " + count.ToString() + " * from Table_Id";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- SqlDataAdapter adapter = new SqlDataAdapter(com);
- DataSet ds = new DataSet();
- adapter.Fill(ds);
- Console.WriteLine("数据记录数为:{0}", ds.Tables[0].Rows.Count);
- }
- }
- 92 /**////
- /// 数据记录行数测试
- ///
- private void Id_Count()
- {
- string ReadSql = "select Count(*) from Table_Id";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- conn.Open();
- object CountResult = com.ExecuteScalar();
- conn.Close();
- Console.WriteLine("数据记录数为:{0}",CountResult);
- }
- }
- 108 /**////
- /// 根据id查询;
- ///
- private void Id_SelectById()
- {
- string ReadSql = "select * from Table_Id where Id="+300000;
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- conn.Open();
- object IdResult = com.ExecuteScalar();
- Console.WriteLine("Id为{0}", IdResult);
- conn.Close();
- }
- }
-
- /**////
- /// Guid测试;
- ///
- private void Guid_InsertTest(int count)
- {
- string InsertSql = "insert into Table_Guid ([Value]) values ({0})";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- conn.Open();
- SqlCommand com = new SqlCommand();
- for (int i = 0; i < count; i++)
- {
- com.Connection = conn;
- com.CommandText = string.Format(InsertSql, i);
- com.ExecuteNonQuery();
- }
- }
- }
- 143 /**////
- /// Guid格式将数据库读到Table
- ///
- private void Guid_ReadToTable(int count)
- {
- string ReadSql = "select top "+count.ToString()+" * from Table_GuID";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- SqlDataAdapter adapter = new SqlDataAdapter(com);
- DataSet ds = new DataSet();
- adapter.Fill(ds);
- Console.WriteLine("数据记录为:{0}", ds.Tables[0].Rows.Count);
- }
- }
- 159 /**////
- /// 数据记录行数测试
- ///
- private void Guid_Count()
- {
- string ReadSql = "select Count(*) from Table_Guid";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- conn.Open();
- object CountResult = com.ExecuteScalar();
- conn.Close();
- Console.WriteLine("数据记录为:{0}", CountResult);
- }
- }
- 175 /**////
- /// 根据Guid查询;
- ///
- private void Guid_SelectById()
- {
- string ReadSql = "select * from Table_Guid where Guid='C1763624-036D-4DB9-A1E4-7E16318C30DE'";
- using (SqlConnection conn = new SqlConnection(Connnection))
- {
- SqlCommand com = new SqlCommand(ReadSql, conn);
- conn.Open();
- object IdResult = com.ExecuteScalar();
- Console.WriteLine("Guid为{0}", IdResult);
- conn.Close();
- }
- }
- }
- 192}
- 193
コードをコピーします3. データベース挿入テスト テスト1 データベースのボリュームは100項目です 結果を出せ テスト2 データベースのボリュームは以下の通りです:10,000点 結果を出せ
テスト3 データベースの項目数は10万点です 結果を出せ テスト4 データベースのボリュームは50万点です 結果を出せ 4. データをデータセットに読み込む テスト1 読み取ったデータ量:100 結果を出せ テスト2 読み取ったデータ量:10,000 結果を出せ テスト3 読み取られたデータ量:100,000 結果を出せ テスト4 読み取られたデータ量:500,000 結果を出せ 4. 総数テストの記録 実験値 5. 条件クエリテストを指定する クエリデータベースの300,000番目のレコードは610,300です。 4. 概要: Guidをメインキーとして使うのはそれほど遅くはありませんが、自動成長インクリメントを使うよりは速いです。
|