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

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

性能優(yōu)化你必須知道的那些事兒

2019-11-17 02:57:30
字體:
供稿:網(wǎng)友

性能優(yōu)化你必須知道的那些事兒

最近有客戶反饋系統(tǒng)導(dǎo)入EXECL進(jìn)行數(shù)據(jù)處理超時了,我當(dāng)時的第一反應(yīng),不可能啊我明明是做過性能優(yōu)化的啊,怎么還會超時呢,這是要有多少條數(shù)據(jù)才可能發(fā)生啊!于是找客戶要來了EXECL,發(fā)現(xiàn)有7500多條數(shù)據(jù),備份完客戶數(shù)據(jù)庫進(jìn)行代碼調(diào)試找出性能差的地方。都是一些平時老生常談的東西,可是又是很容易忽略的地方,這里面就只談兩個點(diǎn),使用String還是StringBuilder,校驗(yàn)數(shù)據(jù)正確性是在循環(huán)里面一條一條的使用SQL取數(shù)呢,還是一次性取出來在代碼里面進(jìn)行校驗(yàn)!下面將用實(shí)際數(shù)據(jù)結(jié)合圖表,給出準(zhǔn)確的答案。

閱讀目錄

  • String和StringBuilder性能差異比較
  • 循環(huán)取數(shù)還是一次性取數(shù)?
  • 示例下載及總結(jié)
回到頂部

String和StringBuilder性能差異比較

  String和StringBuilder的差別這里就不提了,學(xué)習(xí)和工作中常常會聽到拼接字符串要使用StringBuilder對象速度很快,但是可能你只是知道這個知識,實(shí)際開發(fā)工作中有關(guān)注過這一點(diǎn)嗎?我也是當(dāng)客戶反饋之后自己跟蹤用實(shí)際效果才學(xué)會這個知識,后續(xù)開發(fā)中也會銘記這一點(diǎn)!下面的實(shí)際數(shù)據(jù)或許能說明些問題。

分別調(diào)用了這個函數(shù),循環(huán)次數(shù)為 1,5,15,200,500,1500,2500,5500,8500,20000 后面數(shù)據(jù)可以下載最后的DEMO實(shí)驗(yàn)一下,String在這時已經(jīng)是慢到不行了。為了保證數(shù)據(jù)的準(zhǔn)確性,這里每個量級的數(shù)據(jù)都取了十次值,然后求出平均值。

 /// <summary>        /// 對比String和StringBuilder拼接字符串的速度        /// 每種量級測試,取十次時間平均值        /// </summary>        /// <param name="Total">循環(huán)次數(shù)</param>        public static void StringSpeedComparer(int Total){            List<string> list = new List<string>();            for (int i = 0; i < Total; i++)            {                list.Add(Guid.NewGuid().ToString());            }            int iTest = 10;            //總執(zhí)行時間 ms            double TotalMilliseconds = 0;            //String拼接            string strGUID = String.Empty;            while (iTest > 0)            {                DateTime dtBegin = DateTime.Now;                foreach (string temp in list)                {                    strGUID = strGUID + temp + ";";                }                DateTime dtEnd = DateTime.Now;                TotalMilliseconds += (dtEnd - dtBegin).TotalMilliseconds;                iTest--;            }            Console.WriteLine("String拼接{0}個字符串耗時{1}ms", Total, TotalMilliseconds / 10);            //StringBuilder拼接            StringBuilder sb = new StringBuilder();            iTest = 10;            TotalMilliseconds = 0;            while (iTest > 0)            {                DateTime dtBegin = DateTime.Now;                foreach (string temp in list)                {                    sb.AppendFormat("{0};", temp);                }                DateTime dtEnd = DateTime.Now;                TotalMilliseconds += (dtEnd - dtBegin).TotalMilliseconds;                iTest--;            }            Console.WriteLine("StringBuilder拼接{0}個字符串耗時{1}ms", Total, TotalMilliseconds / 10);        }

執(zhí)行結(jié)果如下圖:

 繪制成曲線圖:

 

從上圖可直觀看出來,String拼接是呈幾何形遞增的,而StringBuilder呈線性的,遞增趨勢很慢。在循環(huán)次數(shù)多的情況下使用哪種拼接,相信大家都清楚了吧!在7500的數(shù)量時,可以節(jié)省整整4s的時間,性能是不是提升很多呢?

回到頂部

循環(huán)取數(shù)還是一次性取數(shù)?

  背景:EXECL中有7500行學(xué)生信息數(shù)據(jù),要把這些數(shù)據(jù)導(dǎo)入到學(xué)生表(p_Student)里面,但是要保證學(xué)生編號(StudentNo)唯一,不唯一導(dǎo)入的時候需要給出提示信息。這就需要在后臺代碼里面讀取EXECL里面的學(xué)生信息然后校驗(yàn)學(xué)生編碼在數(shù)據(jù)庫中是否存在,當(dāng)然EXECL中填寫的學(xué)生編號也要校驗(yàn)唯一。下面就來模擬這個過程,以兩種方式比較性能。、

  首先創(chuàng)建學(xué)生信息表,插入7500條數(shù)據(jù),下面是SQL腳本,學(xué)生編號這里插入的是newid,實(shí)際情況不會是這樣的,這里只是會了保證唯一,但是又是無序的,盡可能模擬真實(shí)情形。

/*---------------------------數(shù)據(jù)字典生成工具(V2.1)--------------------------------*/GOIF NOT EXISTS(SELECT 1 FROM sysobjects WHERE id=OBJECT_ID('[p_Student]'))BEGIN/*==============================================================*//* Table: p_Student                                              *//*==============================================================*/CREATE TABLE [dbo].[p_Student](    [StudentGUID] uniqueidentifier   ,    [Name] varchar(40)   ,    [Major] varchar(100)   ,    [Sex] varchar(8)   ,    [StudentNo] varchar(100)   ,    PRIMARY KEY(StudentGUID))    declare @CurrentUser sysnameselect @CurrentUser = user_name()execute sp_addextendedproperty 'MS_Descr

基礎(chǔ)信息準(zhǔn)備好以后,進(jìn)入后臺代碼

 /// <summary>        /// 統(tǒng)計(jì)循環(huán)校驗(yàn)和一次性校驗(yàn)性能差異        /// </summary>        public static void Check(int Total)        {            //這里模擬學(xué)生編號            List<string> listStudetNo = new List<string>();            for (int i = 0; i < Total; i++)            {                listStudetNo.Add(Guid.NewGuid().ToString());            }            using (SqlConnection con = new SqlConnection(SqlCon))            {                con.Open();                string strSQL = "SELECT COUNT(1) FROM dbo.p_Student WHERE StudentNo='{0}'";                SqlCommand cmd = con.CreateCommand();                //循環(huán)校驗(yàn)                double TotalMilliseconds = 0;                for (int i = 0; i < 10; i++)                {                    foreach (string studentNo in listStudetNo)                    {                        DateTime dtBegin = DateTime.Now;                        cmd.CommandText = String.Format(strSQL, studentNo);                        int count = (int)cmd.ExecuteScalar();                        if (count > 0)                        {                            Console.WriteLine("{0}編號重復(fù),請重新錄入!", studentNo);                            return;                        }                        DateTime dtEnd = DateTime.Now;                        TotalMilliseconds += (dtEnd - dtBegin).TotalMilliseconds;                    }                }                Console.WriteLine("循環(huán)校驗(yàn){0}個學(xué)生編號耗時{1}ms", Total, TotalMilliseconds / 10);                //一次性校驗(yàn)                TotalMilliseconds = 0;                strSQL = "SELECT TOP 1 StudentNo FROM dbo.p_Student WHERE StudentNo IN ('{0}')";                for (int i = 0; i < 10; i++)                {                    DateTime dtBegin = DateTime.Now;                    StringBuilder sb = new StringBuilder();                    foreach (string studentNo in listStudetNo)                    {                        sb.AppendFormat("{0};", studentNo);                    }                    cmd.CommandText = String.Format(strSQL,sb.ToString().Substring(0, sb.ToString().Length - 1).Replace(";","','"));                    string no = (string)cmd.ExecuteScalar();                    if (!string.IsNullOrEmpty(no))                    {                        Console.WriteLine("{0}編號重復(fù),請重新錄入!", no);                        return;                    }                    DateTime dtEnd = DateTime.Now;                    TotalMilliseconds += (dtEnd - dtBegin).TotalMilliseconds;                }                Console.WriteLine("一次性校驗(yàn){0}個學(xué)生編號耗時{1}ms", Total, TotalMilliseconds / 10);            }        }

從上圖可直觀看出來,循環(huán)校驗(yàn)和一次性校驗(yàn)都是線性遞增的,一次性校驗(yàn)速度差不多比循環(huán)的快一倍左右。

回到頂部

示例下載及總結(jié)

示例sql,示例代碼DEMO

其實(shí)性能優(yōu)化不僅僅只有這么一點(diǎn),需要在日常工作中總結(jié),這次性能優(yōu)化還有一點(diǎn)也令我驚嘆,有一條SQL未優(yōu)化之前執(zhí)行需要20s左右,給表添加了索引,速度刷的一下變成0s了,最終性能問題圓滿解決了。

性能優(yōu)化思想:

1:大量字符串拼接請采用StringBuilder

2:千萬不要在大量循環(huán)里面循環(huán)查SQL,考慮是否能用一次性查詢代替,或者一次性把數(shù)據(jù)查詢出來在代碼里面進(jìn)行邏輯判斷

3:SQL執(zhí)行速度慢,可以采用執(zhí)行計(jì)劃看看是否表缺少索引。

好了本篇到這里就要結(jié)束了,如

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 门源| 夏河县| 无锡市| 渝中区| 平昌县| 卓资县| 汤原县| 兰坪| 洛隆县| 乐业县| 枝江市| 财经| 行唐县| 曲周县| 南宁市| 德兴市| 额尔古纳市| 定日县| 会东县| 成武县| 涞水县| 大洼县| 大竹县| 澎湖县| 上栗县| 三门峡市| 西吉县| 霸州市| 云林县| 北碚区| 建昌县| 南京市| 吕梁市| 屯门区| 盐源县| 万宁市| 延寿县| 迭部县| 芒康县| 黄龙县| 扬州市|