1. 개요:
우리 데이터베이스 설계에서는 데이터베이스의 기본 키가 필수적이며, 기본 키의 설계는 전체 데이터베이스 설계에 큰 영향을 미칩니다. 자동 증분 필드와 Guid 필드의 성능을 비교할 것이며, 토론 환영합니다.
2. 소개:
1. 자기 증분 장
자기 증가 필드는 매번 순차적으로 증가하여 테이블의 주요 키가 반복되지 않도록 합니다. 자기 증가 필드 타입의 최대 값을 초과하거나 처음부터 증가하지 않는 한, 이는 거의 불가능합니다. 자기 증가 필드를 기본 키로 사용하는 것은 매우 간단하며, 보통 테이블을 만들 때 자가 증가 속성을 선언하면 됩니다.
자가 증가 값은 시스템에서 유지되어야 하는 모든 전역 데이터 값이며, 데이터가 삽입될 때마다 값이 증가합니다. 동시 환경에서는 동등한 값이 고유 정체성을 생성하므로, 각 증분 값은 이 전역 값으로 잠금되고 해제되어야 고유성을 보장합니다. 이것은 성능 문제를 동반하는 병목 현상이 될 수 있습니다.
데이터를 마이그레이션하거나 가져올 때 자가 증분 필드가 중복될 수 있는데, 이는 분명 악몽입니다(저도 이미 겪은 경험이 있습니다).
분산 데이터베이스를 구축하고 싶다면, 이 자기 증가 필드는 문제가 됩니다. 이는 분산 데이터베이스에서는 서로 다른 데이터베이스에서 같은 이름을 가진 테이블을 동기식으로 복제해야 할 수 있기 때문입니다. 데이터베이스 테이블의 자기 증가 값은 동일한 테이블의 자기 증가 값과 다른 데이터베이스에서 중복될 가능성이 높습니다.
2. 고유식별자(Guid) 필드
MS SQL 데이터베이스에서는 필드 타입을 고유식별자(uniqueidentifier)로 지정하여 테이블 구조를 생성할 수 있으며, NewID()를 사용해 기본 값을 생성하여 고유 Guid(전역 고유 식별자)를 생성할 수 있습니다.
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 데이터베이스 물건은 다음과 같습니다: 100,000개 결과를 돌려봐 테스트 4 데이터베이스 양은 500,000개 항목입니다 결과를 돌려봐 4. 데이터를 데이터셋에 읽습니다 테스트 1 읽힌 데이터량: 100 결과를 돌려봐 테스트 2 읽힌 데이터량: 10,000 결과를 돌려봐 테스트 3 읽힌 데이터량: 100,000 결과를 돌려봐 테스트 4 읽힌 데이터량: 500,000 결과를 돌려봐 4. 총 수 검사 기록 검사 결과 5. 조건 쿼리 테스트를 지정한다 쿼리 데이터베이스의 300,000번째 레코드는 610,300입니다. 4. 요약: Guid를 메인 키로 사용하는 것은 매우 느리진 않지만, 자동 성장 증가 키보다는 빠릅니다.
|