国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

可排序的 COMB 類型 GUID

2019-11-17 02:54:19
字體:
來源:轉載
供稿:網友

可排序的 COMB 類型 GUID

最新代碼在這兒:CombGuid.cs

首先這里不做GUID與整形作為主鍵的優劣之爭,GUID自有它優勢,但GUID本身是亂序的,會對索引的維護帶來性能上的損耗,數據量越大越明顯。

COMB 類型 GUID 是由Jimmy Nilsson在他的“The Cost of GUIDs as PRimary Keys”一文中設計出來的。

基本設計思路是這樣的:既然GUID數據因毫無規律可言造成索引效率低下,影響了系統的性能,那么能不能通過組合的方式,保留GUID的前10個字節,用后6個字節表示GUID生成的時間(DateTime),這樣我們將時間信息與GUID組合起來,在保留GUID的唯一性的同時增加了有序性,以此來提高索引效率。

在NHibernate已經有代碼實現,基于1/300秒為單位生成的,但實際Windows操作系統時鐘更新頻率多核15ms(1/67秒),單核10ms,是無法精確到1/300秒的,而且在短時間內生成大量CombGuid時,DateTime.Now有可能是不變化的,我在測試中遇到了這種情況,結果生成了5萬條CombGuid記錄,其中有兩萬多條是重復的,這樣在實際生產環境中如果數據插入量非常大而且頻繁的情況下,CombGuid排序的優勢就沒有了。

針對NHibernate的代碼進行了些優化,已當前時間1/10000秒為基礎創建CombGuid,如果當前時間基數與上次創建時相同,直接累加1,確保不產生重復的CombGuid:

private static readonly DateTime _CombBaseDate = new DateTime(1900, 1, 1);private static Int32 _LastDays; // 天數private static Int32 _LastTenthMilliseconds; // 單位:1/10 毫秒private static readonly Int32 _MaxTenthMilliseconds = 863999999;#region - NewComb -/// <summary>初始化 CombGuid 結構的新實例。</summary>/// <returns>一個新的 CombGuid 對象。</returns>public static CombGuid NewComb(){var guidArray = Guid.NewGuid().ToByteArray();var now = DateTime.Now;// Get the days and milliseconds which will be used to build the Byte Stringvar days = new TimeSpan(now.Ticks - _CombBaseDate.Ticks).Days;var tenthMilliseconds = (Int32)(now.TimeOfDay.TotalMilliseconds * 10D);var lastDays = _LastDays;var lastTenthMilliseconds = _LastTenthMilliseconds;if (days > lastDays){Interlocked.CompareExchange(ref _LastDays, days, lastDays);Interlocked.CompareExchange(ref _LastTenthMilliseconds, tenthMilliseconds, lastTenthMilliseconds);}else{if (tenthMilliseconds > lastTenthMilliseconds){Interlocked.CompareExchange(ref _LastTenthMilliseconds, tenthMilliseconds, lastTenthMilliseconds);}else{if (_LastTenthMilliseconds < Int32.MaxValue) { Interlocked.Increment(ref _LastTenthMilliseconds); }tenthMilliseconds = _LastTenthMilliseconds;}}// Convert to a Byte arrayvar daysArray = BitConverter.GetBytes(days);var msecsArray = BitConverter.GetBytes(tenthMilliseconds);// Reverse the bytes to match SQL Servers orderingArray.Reverse(daysArray);Array.Reverse(msecsArray);// Copy the bytes into the guidArray.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);//Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);Array.Copy(msecsArray, 0, guidArray, guidArray.Length - 4, 4);return new CombGuid(guidArray, true);}#endregion

這樣理論上一天之內允許生成 864000000 個不重復的CombGuid;如果當天生成的個數大于 864000000 ,會一直累加 1 直到 2147483647 ,也就是說實際一天之內能生成 2147483647 個不重復的CombGuid。

完整CombGuid代碼,參考了.net fx內部guid、sqlguid的部分方法:

/* * CombGuid *  * 作者:海洋餅干 * 時間:2014-09-10 18:42:51 * 博客:http://m.survivalescaperooms.com/hmking/ * 版權:版權所有 (C) Eme Development Team 2014*/using System;using System.Collections.Generic;using System.ComponentModel;using System.Data.SqlTypes;using System.Runtime.InteropServices;using System.Threading;using System.xml;using System.Xml.Schema;using System.Xml.Serialization;namespace HmFramework{/// <summary>COMB 類型 GUID,要存儲在數據庫中或要從數據庫中檢索的 GUID。</summary>/// <remarks>COMB 類型 GUID 是由Jimmy Nilsson在他的“The Cost of GUIDs as Primary Keys”一文中設計出來的。/// <para>基本設計思路是這樣的:既然GUID數據因毫無規律可言造成索引效率低下,影響了系統的性能,那么能不能通過組合的方式,/// 保留GUID的前10個字節,用后6個字節表示GUID生成的時間(DateTime),這樣我們將時間信息與GUID組合起來,/// 在保留GUID的唯一性的同時增加了有序性,以此來提高索引效率。</para>/// <para>也許有人會擔心GUID減少到10字節會造成數據出現重復,其實不用擔心,/// 后6字節的時間精度可以達到 1/10000 秒,兩個COMB類型數據完全相同的可能性是在這 1/10000 秒內生成的兩個GUID前10個字節完全相同,這幾乎是不可能的!</para>/// <para>理論上一天之內允許生成 864000000 個不重復的CombGuid;如果當天生成的個數大于 864000000 ,會一直累加 1 直到 2147483647 ,/// 也就是說實際一天之內能生成 2147483647 個不重復的CombGuid。</para>/// </remarks>public struct CombGuid : INullable, IComparable, IComparable<CombGuid>, IEquatable<CombGuid>, IXmlSerializable{#region -- Fields --private static readonly String _NullString = "nil";private static readonly Int32 _SizeOfGuid = 16;// Comparison orders.private static readonly Int32[] _GuidComparisonOrders = new Int32[16] { 10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3 };// Parse orders.private static readonly Int32[] _GuidParSEOrders32 = new Int32[32] { 30, 31, 28, 29, 26, 27, 24, 25, 22, 23, 20, 21,18, 19, 16, 17,12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};private static readonly Int32[] _GuidParseOrders36 = new Int32[36] { 34, 35, 32, 33, 30, 31, 28, 29, 27,25, 26, 23, 24,22,20, 21, 18, 19,17,13, 14, 15, 16, 12,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};// the CombGuid is null if m_value is nullprivate Byte[] m_value;#endregion#region -- 屬性 --/// <summary>CombGuid 結構的只讀實例,其值空。</summary>public static readonly CombGuid Null = new CombGuid(true);/// <summary>獲取 CombGuid 結構的值。 此屬性為只讀。</summary>public Guid Value{get{if (IsNull){throw new SqlNullValueException();}else{return new Guid(m_value);}}}/// <summary>獲取 CombGuid 結構的日期時間屬性。/// <para>如果同一時間批量生成了大量的 CombGuid 時,返回的日期時間是不準確的!</para>/// </summary>public DateTime DateTime{get{if (IsNull){throw new SqlNullValueException();}else{var daysArray = new Byte[4];var msecsArray = new Byte[4];// Copy the date parts of the guid to the respective Byte arrays.Array.Copy(m_value, m_value.Length - 6, daysArray, 2, 2);Array.Copy(m_value, m_value.Length - 4, msecsArray, 0, 4);// Reverse the arrays to put them into the appropriate orderArray.Reverse(daysArray);Array.Reverse(msecsArray);// Convert the bytes to intsvar days = BitConverter.ToInt32(daysArray, 0);var msecs = BitConverter.ToInt32(msecsArray, 0);var date = _CombBaseDate.AddDays(days);if (msecs > _MaxTenthMilliseconds) { msecs = _MaxTenthMilliseconds; }msecs /= 10;return date.AddMilliseconds(msecs);}}}#endregion#region -- 構造 --/// <summary>實例化一個空 CombGuid 結構</summary>private CombGuid(Boolean isNull){m_value = null;}/// <summary>使用指定的字節數組初始化 CombGuid 結構的新實例。</summary>/// <param name="value">包含初始化 CombGuid 的值的 16 元素字節數組。</param>public CombGuid(Byte[] value): this(value, false) { }/// <summary>使用指定的字節數組初始化 CombGuid 結構的新實例。</summary>/// <param name="value">包含初始化 CombGuid 的值的 16 元素字節數組。</param>/// <param name="isOwner">是否 CombGuid 結構直接使用</param>private CombGuid(Byte[] value, Boolean isOwner){if (value == null || value.Length != _SizeOfGuid){throw new ArgumentException("value 的長度不是 16 個字節。");}if (isOwner){m_value = value;}else{m_value = new Byte[_SizeOfGuid];value.CopyTo(m_value, 0);}}/// <summary>使用指定字符串所表示的值初始化 CombGuid 結構的新實例。</summary>/// <param name="comb">包含下面任一格式的 CombGuid 的字符串(“d”表示忽略大小寫的十六進制數字):/// <para>32 個連續的數字 dddddddddddddddddddddddddddddddd </para>/// <para>- 或 - </para>/// <para>12 和 4、4、4、8 位數字的分組,各組之間有連線符,dddddddddddd-dddd-dddd-dddd-dddddddd</para>/// </param>public CombGuid(String comb){ValidationHelper.ArgumentNullOrEmpty(comb, "comb");Int32 a; Int16 b, c; Byte[] d;if (new GuidParser(comb).TryParse(out a, out b, out c, out d)){m_value = new Byte[_SizeOfGuid];Init(a, b, c, d);}else{throw CreateFormatException(comb);}}private static Exception CreateFormatException(String s){return new FormatException(String.Format("Invalid CombGuid format: {0}", s));}/// <summary>使用指定的 Guid 參數初始化 CombGuid 結構的新實例。</summary>/// <param name="g">一個 Guid</param>public CombGuid(Guid g){m_value = g.ToByteArray();}/// <summary>使用指定的整數和字節數組初始化 CombGuid 類的新實例。</summary>/// <param name="a">CombGuid 的開頭四個字節。</param>/// <param name="b">CombGuid 的下兩個字節。</param>/// <param name="c">CombGuid 的下兩個字節。</param>/// <param name="d">CombGuid 的其余 8 個字節</param>public CombGuid(Int32 a, Int16 b, Int16 c, Byte[] d){ValidationHelper.ArgumentNull(d, "d");// Check that array is not too bigif (d.Length != 8) { throw new ArgumentException("d 的長度不是 8 個字節。"); }m_value = new Byte[_SizeOfGuid];Init(a, b, c, d);}private void Init(Int32 a, Int16 b, Int16 c, Byte[] d){m_value[0] = (Byte)(a);m_value[1] = (Byte)(a >> 8);m_
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 成武县| 将乐县| 潢川县| 华池县| 洞口县| 安庆市| 太康县| 平罗县| 桃源县| 宁乡县| 康马县| 汤原县| 潮安县| 昭苏县| 吴忠市| 合肥市| 上高县| 榆树市| 尖扎县| 大姚县| 石门县| 故城县| 湖南省| 丰县| 兴业县| 高台县| 闻喜县| 福鼎市| 辽源市| 江源县| 繁峙县| 荔波县| 商洛市| 普格县| 大埔县| 平谷区| 浦东新区| 吉隆县| 玉溪市| 甘德县| 大方县|