1. Visão geral:
No nosso design de banco de dados, a chave primária do banco de dados é essencial, e o design da chave primária tem grande impacto no design de todo o banco de dados. Vou comparar o desempenho dos campos auto-incrementais e dos campos GUID, bem-vindo para discutir.
2. Introdução:
1. Campos auto-incrementais
Os campos auto-incrementais são incrementados sequencialmente a cada vez, garantindo que as chaves primárias em uma tabela não sejam repetidas. A menos que o valor máximo do tipo de campo auto-incrementante seja ultrapassado e incrementado do zero, isso é quase impossível. É muito simples usar campos auto-incrementais como chaves primárias, geralmente apenas declarar atributos auto-incrementáveis ao construir uma tabela.
Valores auto-incrementais são todos os valores globais de dados que precisam ser mantidos no sistema, e o valor é incrementado toda vez que os dados são inseridos. Em um ambiente concorrente onde o equivalente gera uma identidade única, cada valor incremental deve ser bloqueado e desbloqueado com esse valor global para garantir a unicidade do incremento. Isso pode ser um gargalo simultâneo que envolve alguns problemas de desempenho.
Ao migrar ou importar dados, campos auto-incrementais podem ser duplicados, o que é, sem dúvida, um pesadelo (eu já sofri com isso).
Se você quiser construir um banco de dados distribuído, esse campo auto-incremental é um problema. Isso ocorre porque, em um banco de dados distribuído, tabelas com o mesmo nome de diferentes bancos podem precisar ser replicadas de forma síncrona. O valor auto-incremental de uma tabela de banco de dados provavelmente será duplicado com o valor auto-incremental da mesma tabela em outro banco de dados.
2. campo UniqueIdentifier (Guid)
Em bancos de dados MS SQL, a estrutura de tabela pode ser criada especificando o tipo de campo como identifiador único, e seu valor padrão pode ser gerado usando NewID() para gerar um Guid único (Identificador Globalmente Único).
Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.
A vantagem do GUID é que o ID gerado é relativamente único, seja exportando dados ou fazendo desenvolvimento passo a passo, não haverá problemas. No entanto, o ID gerado é relativamente longo, e o espaço do banco de dados também está ocupado, então não há necessidade de considerar isso, pois o custo do armazenamento externo diminui. Além disso, Guid não é fácil de lembrar e, nesse aspecto, não é tão bom quanto campos incrementais automáticos, o que não é muito conveniente ao depurar programas.
3. Testes:
1. Testar o ambiente
Sistema operacional: Windows Server 2003 R2 Enterprise Edition Service Pack 2
Banco de dados: MS SQL 2005
CPU:Intel(R) Pentium(R) 4 CPU 3.40GHz
Memória: DDRII. 667 1G
Disco rígido: WD 80G
2. Scripts de banco de dados
- --自增量字段表
- 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
Copiar código Código de teste
- 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
Copiar código3. Teste de inserção de banco de dados Teste 1 O volume do banco de dados é: 100 itens Execute o resultado Teste 2 O volume do banco de dados é: 10.000 itens Execute o resultado
Teste 3 O volume do banco de dados é: 100.000 itens Execute o resultado Teste 4 O volume do banco de dados é: 500.000 itens Execute o resultado 4. Leia os dados no DataSet Teste 1 Quantidade de dados lidos: 100 Execute o resultado Teste 2 Quantidade de dados lidos: 10.000 Execute o resultado Teste 3 Quantidade de dados lidos: 100.000 Execute o resultado Teste 4 Quantidade de dados lidos: 500.000 Execute o resultado 4. Registrar o teste total de números Resultados dos testes 5. Especifique o teste de consulta de condição O 300.000º registro no banco de dados de consultas é 610.300. 4. Resumo: Usar Guid como chave principal não é muito lento, mas é mais rápido do que usar incrementos de crescimento automático.
|