Эта статья является зеркальной статьёй машинного перевода, пожалуйста, нажмите здесь, чтобы перейти к оригиналу.

Вид: 13193|Ответ: 0

[Чаевые] Сравните производительность первичного ключа поля Guid с помощью самоинкрементального поля в библиотеке

[Скопировать ссылку]
Опубликовано 26.10.2015 9:37:04 | | | |
1. Обзор:

В нашем проектировании базы данных первичный ключ базы данных является необходимым, и дизайн первичного ключа оказывает значительное влияние на дизайн всей базы данных. Я сравню производительность автоинкрементальных полей и Guid-полей — добро пожаловать к обсуждению.

2. Введение:

1. Самоинкрементальные поля

      Самоинкрементальные поля увеличиваются последовательно каждый раз, чтобы первичные ключи в таблице не повторялись. Если максимальное значение самоувеличивающегося поля не превышается и не увеличивается с нуля, это практически невозможно. Очень просто использовать самоинкрементальные поля в качестве первичных ключей, обычно при построении таблицы просто указывают атрибуты самоувеличения.

      Самоинкрементальные значения — это все глобальные значения данных, которые необходимо поддерживать в системе, и значение увеличивается каждый раз при вставке данных. В параллельной среде, где эквивалент генерирует уникальную идентичность, каждое инкрементальное значение должно быть заблокировано и разблокировано с этим глобальным значением, чтобы обеспечить уникальность инкремента. Это может быть одновременно узким местом, связанным с проблемами производительности.

При миграции или импорте данных самоинкрементальные поля могут дублироваться, что, без сомнения, кошмар (я уже с этим сталкивался).

      Если вы хотите создать распределённую базу данных, это самоинкрементальное поле — проблема. Это связано с тем, что в распределённой базе данных таблицы с одинаковым именем из разных баз данных могут потребовать синхронного репликации. Самоинкрементальное значение таблицы базы данных, скорее всего, будет дублироваться с самоинкрементальным значением той же таблицы в другой базе данных.

2. уникальное отличие (Guid) поле

В базах данных MS SQL структура таблицы может быть создана, указав тип поля как уникальный идентификатор, а её значение по умолчанию может быть сгенерировано с помощью NewID() для генерации уникального Guid (Глобально уникальный идентификатор).

Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.

Преимущество GUID в том, что сгенерированный идентификатор относительно уникален: будь то экспорт данных или пошаговая разработка, проблем не возникнет. Однако генерируемый ID относительно длинный, и пространство базы данных тоже занято, поэтому учитывать это не нужно, поскольку стоимость внешнего хранилища снижается. Кроме того, Guid сложно запомнить, и в этом отношении он хуже автоматических инкрементальных полей, что не очень удобно при отладке программ.

3. Тестирование:

1. Проверьте окружающую среду

Операционная система: Windows Server 2003 R2 Enterprise Edition Service Pack 2

База данных: MS SQL 2005

CPU:Intel(R) Pentium(R) 4 CPU 3.40GHz

Память: DDRII. 667 1G

Жёсткий диск: WD 80G

2. Скрипты базы данных
  1. --自增量字段表
  2. CREATE TABLE [dbo].[Table_Id](
  3.     [Id] [int] IDENTITY(1,1) NOT NULL,
  4.     [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  5. CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED
  6. (
  7.     [Id] ASC
  8. )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
  9. ) ON [PRIMARY]

  10. GO
  11. --Guid字段表
  12. CREATE TABLE [dbo].[Table_Guid](
  13.     [Guid] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Table_Guid_Guid]  DEFAULT (newid()),
  14.     [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  15. CONSTRAINT [PK_Table_Guid] PRIMARY KEY CLUSTERED
  16. (
  17.     [Guid] ASC
  18. )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
  19. ) ON [PRIMARY]

  20. GO
Копирование кода
Тестовый код
  1. 1using System;
  2.   2using System.Collections.Generic;
  3.   3using System.Text;
  4.   4using System.Data.SqlClient;
  5.   5using System.Diagnostics;
  6.   6using System.Data;
  7.   8namespace GuidTest
  8.   9{
  9.    class Program
  10.    {
  11.        string Connnection = "server=.;database=GuidTest;Integrated Security=true;";
  12.        static void Main(string[] args)
  13.        {
  14.            Program app = new Program();
  15.            int Count = 10000;
  16.            Console.WriteLine("数据记录数为{0}",Count);
  17.            //自动id增长测试;
  18.            Stopwatch WatchId = new Stopwatch();
  19.            Console.WriteLine("自动增长id测试");
  20.            Console.WriteLine("开始测试");
  21.            WatchId.Start();
  22.            Console.WriteLine("测试中");
  23. 25            app.Id_InsertTest(Count);
  24.            //app.Id_ReadToTable(Count);
  25.            //app.Id_Count();
  26. 29            //查询第300000条记录;
  27.            //app.Id_SelectById();
  28. 32            WatchId.Stop();
  29.            Console.WriteLine("时间为{0}毫秒",WatchId.ElapsedMilliseconds);
  30.            Console.WriteLine("测试结束");
  31. 36            Console.WriteLine("-----------------------------------------");
  32.            //Guid测试;
  33.            Console.WriteLine("Guid测试");
  34.            Stopwatch WatchGuid = new Stopwatch();
  35.            Console.WriteLine("开始测试");
  36.            WatchGuid.Start();
  37.            Console.WriteLine("测试中");
  38. 44            app.Guid_InsertTest(Count);
  39.            //app.Guid_ReadToTable(Count);
  40.            //app.Guid_Count();
  41. 48            //查询第300000条记录;
  42.            //app.Guid_SelectById();
  43. 51            WatchGuid.Stop();
  44.            Console.WriteLine("时间为{0}毫秒", WatchGuid.ElapsedMilliseconds);
  45.            Console.WriteLine("测试结束");
  46.            Console.Read();
  47.        }
  48. 57        /**////
  49.        /// 自动增长id测试
  50.        ///
  51.        private void Id_InsertTest(int count)
  52.        {
  53.            string InsertSql="insert into Table_Id ([Value]) values ({0})";
  54.            using (SqlConnection conn = new SqlConnection(Connnection))
  55.            {
  56.                conn.Open();
  57.                SqlCommand com = new SqlCommand();
  58.                for (int i = 0; i < count; i++)
  59.                {
  60.                    com.Connection = conn;
  61.                    com.CommandText = string.Format(InsertSql, i);
  62.                    com.ExecuteNonQuery();
  63.                }
  64.            }
  65.        }
  66. 76        /**////
  67.        /// 将数据读到Table
  68.        ///
  69.        private void Id_ReadToTable(int count)
  70.        {
  71.            string ReadSql = "select top " + count.ToString() + " * from Table_Id";
  72.            using (SqlConnection conn = new SqlConnection(Connnection))
  73.            {
  74.                SqlCommand com = new SqlCommand(ReadSql, conn);
  75.                SqlDataAdapter adapter = new SqlDataAdapter(com);
  76.                DataSet ds = new DataSet();
  77.                adapter.Fill(ds);
  78.                Console.WriteLine("数据记录数为:{0}", ds.Tables[0].Rows.Count);
  79.            }
  80.        }
  81. 92        /**////
  82.        /// 数据记录行数测试
  83.        ///
  84.        private void Id_Count()
  85.        {
  86.            string ReadSql = "select Count(*) from Table_Id";
  87.            using (SqlConnection conn = new SqlConnection(Connnection))
  88.            {
  89.                SqlCommand com = new SqlCommand(ReadSql, conn);
  90.                conn.Open();
  91.                object CountResult = com.ExecuteScalar();
  92.                conn.Close();
  93.                Console.WriteLine("数据记录数为:{0}",CountResult);
  94.            }
  95.        }
  96. 108        /**////
  97.        /// 根据id查询;
  98.        ///
  99.        private void Id_SelectById()
  100.        {
  101.            string ReadSql = "select * from Table_Id where Id="+300000;
  102.            using (SqlConnection conn = new SqlConnection(Connnection))
  103.            {
  104.                SqlCommand com = new SqlCommand(ReadSql, conn);
  105.                conn.Open();
  106.                object IdResult = com.ExecuteScalar();
  107.                Console.WriteLine("Id为{0}", IdResult);
  108.                conn.Close();
  109.            }
  110.        }
  111.       
  112.        /**////
  113.        /// Guid测试;
  114.        ///
  115.        private void Guid_InsertTest(int count)
  116.        {
  117.            string InsertSql = "insert into Table_Guid ([Value]) values ({0})";
  118.            using (SqlConnection conn = new SqlConnection(Connnection))
  119.            {
  120.                conn.Open();
  121.                SqlCommand com = new SqlCommand();
  122.                for (int i = 0; i < count; i++)
  123.                {
  124.                    com.Connection = conn;
  125.                    com.CommandText = string.Format(InsertSql, i);
  126.                    com.ExecuteNonQuery();
  127.                }
  128.            }
  129.        }
  130. 143        /**////
  131.        /// Guid格式将数据库读到Table
  132.        ///
  133.        private void Guid_ReadToTable(int count)
  134.        {
  135.            string ReadSql = "select top "+count.ToString()+" * from Table_GuID";
  136.            using (SqlConnection conn = new SqlConnection(Connnection))
  137.            {
  138.                SqlCommand com = new SqlCommand(ReadSql, conn);
  139.                SqlDataAdapter adapter = new SqlDataAdapter(com);
  140.                DataSet ds = new DataSet();
  141.                adapter.Fill(ds);
  142.                Console.WriteLine("数据记录为:{0}", ds.Tables[0].Rows.Count);
  143.            }
  144.        }
  145. 159        /**////
  146.        /// 数据记录行数测试
  147.        ///
  148.        private void Guid_Count()
  149.        {
  150.            string ReadSql = "select Count(*) from Table_Guid";
  151.            using (SqlConnection conn = new SqlConnection(Connnection))
  152.            {
  153.                SqlCommand com = new SqlCommand(ReadSql, conn);
  154.                conn.Open();
  155.                object CountResult = com.ExecuteScalar();
  156.                conn.Close();
  157.                Console.WriteLine("数据记录为:{0}", CountResult);
  158.            }
  159.        }
  160. 175        /**////
  161.        /// 根据Guid查询;
  162.        ///
  163.        private void Guid_SelectById()
  164.        {
  165.            string ReadSql = "select * from Table_Guid where Guid='C1763624-036D-4DB9-A1E4-7E16318C30DE'";
  166.            using (SqlConnection conn = new SqlConnection(Connnection))
  167.            {
  168.                SqlCommand com = new SqlCommand(ReadSql, conn);
  169.                conn.Open();
  170.                object IdResult = com.ExecuteScalar();
  171.                Console.WriteLine("Guid为{0}", IdResult);
  172.                conn.Close();
  173.            }
  174.        }
  175.    }
  176. 192}
  177. 193
Копирование кода
3. Тест вставки базы данных
Тест 1
Объём базы данных: 100 элементов
Запустите результат
Тест 2
Объём базы данных: 10 000 элементов
Запустите результат

Тест 3
Объём базы данных: 100 000 элементов
Запустите результат
Тест 4
Объём базы данных: 500 000 элементов
Запустите результат
4. Прочитайте данные в DataSet
Тест 1
Количество прочитанных данных: 100
Запустите результат
Тест 2
Количество прочитанных данных: 10 000
Запустите результат
Тест 3
Количество прочитанных данных: 100 000
Запустите результат
Тест 4
Количество прочитанных данных: 500 000
Запустите результат
4. Запишите общий тест на количество
Результаты тестов
5. Закажите тест запроса к условию
300 000-я запись в базе запросов — 610 300.
4. Резюме:
Использование Guid в качестве основного ключа не очень медленное, но быстрее, чем автоматическое увеличение инкрементов.





Предыдущий:asp.net преобразовать бинарный контент Base64 в изображения и хранить их локально
Следующий:Строка[3]: свойство Size имеет недопустимый размер 0.
Отказ:
Всё программное обеспечение, программные материалы или статьи, публикуемые Code Farmer Network, предназначены исключительно для учебных и исследовательских целей; Вышеуказанный контент не должен использоваться в коммерческих или незаконных целях, иначе пользователи несут все последствия. Информация на этом сайте взята из Интернета, и споры по авторским правам не имеют отношения к этому сайту. Вы должны полностью удалить вышеуказанный контент с компьютера в течение 24 часов после загрузки. Если вам нравится программа, пожалуйста, поддержите подлинное программное обеспечение, купите регистрацию и получите лучшие подлинные услуги. Если есть нарушение, пожалуйста, свяжитесь с нами по электронной почте.

Mail To:help@itsvse.com