<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

    關(guān)于SQL函數(shù)效率的一些測試與思考

    在項目中我們經(jīng)常能遇到數(shù)據(jù)庫有“一對多”的關(guān)系,比如下面兩張表:

      Student:

      Class:

      Class-Student就這樣構(gòu)成了一個簡單的一對多關(guān)系。當(dāng)然在實際的項目中,也可以再建立一張Relation表來保存他們之間的關(guān)系,在這里為了簡單,就不做Relation表了。

      現(xiàn)在在項目中,我需要將Class表中的數(shù)據(jù)list顯示,當(dāng)然也想顯示選擇了這門課的Student的StuName。也可以說是將一對多關(guān)系轉(zhuǎn)換為一對一關(guān)系。我所期望的顯示格式是這樣的:

      要做到這一點并不難,大體有兩種思路:

      1、在數(shù)據(jù)庫中寫一個函數(shù)

      2、在程序中獲取表Class與表Student所有數(shù)據(jù),然后對比ClassID

      那么,那種方法效率比較高呢?于是我寫了下面的代碼來進行一個簡單的測試

    View Code


        class Program
        {
            static void Main(string[] args)
            {
                Sql sql = new Sql();
                Stopwatch time1 = new Stopwatch();
                Stopwatch time2 = new Stopwatch();
                for (int j = 0; j < 10; j++)
                {
                    time2.Start();
                    for (int i = 0; i < 1000; i++)
                    {
                        string sql1 = "select ID,[StuName],[ClassID] FROM [Student]";
                        string sql2 = " SELECT  ID,ClassName from Class";
                        List<string> item = new List<string>();
                        string bl="";
                        DataTable dt1 = sql.getData(sql1);
                        DataTable dt2 = sql.getData(sql2);
                        foreach (DataRow dtRow2 in dt2.Rows)
                        {
                            foreach (DataRow dtRow1 in dt1.Rows)
                            {
                                if (dtRow1["ClassID"].ToString() == dtRow2["ID"].ToString())
                                {
                                     bl+=dtRow1["StuName"].ToString()+",";
                                }   
                            }
                            item.Add(bl);
                            bl = "";
                        }
                    }
                    time2.Stop();
                    Console.WriteLine(time2.Elapsed.ToString());

                    time1.Start();
                    for (int i = 0; i < 1000; i++)
                    {
                        string sql3 = "SELECT C.ID, C.ClassName, dbo.f_getStuNamesByClassID(C.ID)as stuName FROM Class C";
                        DataTable dt = sql.getData(sql3);
                    }
                    time1.Stop();
                    Console.WriteLine(time1.Elapsed.ToString());


                    float index = (float)time1.Elapsed.Ticks / (float)time2.Elapsed.Ticks;
                    Console.WriteLine("效率比" + index.ToString());
                    Console.WriteLine("=============================");
                }

                Console.ReadLine();
            }
        }


    View Code


        class Sql
        {
            public DataTable getData(string sql)
            {
                SqlConnection conn = new SqlConnection();
                conn.ConnectionString = "Data Source=.\\SQLEXPRESS;Initial Catalog=Test;User Id=sa;Password=1;";
                SqlCommand comm = new SqlCommand(sql, conn);
                conn.Open();
                SqlDataAdapter da = new SqlDataAdapter(comm);
                DataSet ds = new DataSet();
                da.Fill(ds, "ds");
                conn.Close();
                return ds.Tables[0];
            }
        }

    View Code

    --根據(jù)課程ID,返回選此課程的學(xué)生的名字,以逗號隔開
    ALTER function [dbo].[f_getStuNamesByClassID] (@ID int)
    RETURNS nvarchar(50)
    begin
        declare @Result nvarchar(50);
        declare @stuName nvarchar(50);
        Set @Result='';

        declare cur cursor for
        (
            SELECT S.StuName FROM Class C
            LEFT JOIN Student S ON C.ID=S.ClassID
            WHERE C.ID=@ID
        )
        open cur;
        fetch next from cur into @stuName;
        while(@@fetch_status=0)
        begin
            set @Result=@Result+@stuName+',';
            fetch next from cur into @stuName;
        end;
    --去除最后多余的一個逗號
        IF @Result <> '' 
            SET @Result=SUBSTRING(@Result, 1, LEN(@Result)-1);
        ELSE
            SET @Result=NULL;
        return @Result;
    en

      測試結(jié)果如下:

      00:00:00.5466790
      00:00:00.7753704
      效率比1.418329
      =============================
      00:00:01.0251996
      00:00:01.5594629
      效率比1.521131
      =============================
      00:00:01.5124349
      00:00:02.3286227
      效率比1.539652
      =============================
      00:00:01.9882458
      00:00:03.1007960
      效率比1.559564
      =============================
      00:00:02.4476305
      00:00:03.8717636
      效率比1.581842
      =============================
      00:00:02.9129007
      00:00:04.6332828
      效率比1.590608
      =============================
      00:00:03.4006140
      00:00:05.3971930
      效率比1.587123
      =============================
      00:00:03.8655281
      00:00:06.2574500
      效率比1.618783
      =============================
      00:00:04.4532249
      00:00:07.0674710
      效率比1.587046
      =============================
      00:00:04.9540083
      00:00:07.8596999
      效率比1.586533
      =============================

     分析一下測試結(jié)果,不難發(fā)現(xiàn)每一個一千次所用的時間基本符合一個等差數(shù)列。當(dāng)然第一個一千次由于要初始化,所以顯得慢一些。

      總體來說,在程序中用處理一對多關(guān)系,比在數(shù)據(jù)庫中用函數(shù)處理效率要高35%這樣。

      那么如果我們在Student表中再添加一行這樣的數(shù)據(jù):

      測試結(jié)果如下:

      00:00:00.5519228
      00:00:00.8206084
      效率比1.486817
      =============================
      00:00:01.0263686
      00:00:01.5813210
      效率比1.540695
      =============================
      00:00:01.4886327
      00:00:02.3516000
      效率比1.579705
      =============================
      00:00:01.9807901
      00:00:03.1495472
      效率比1.590046
      =============================
      00:00:02.4613411
      00:00:03.9278171
      效率比1.595804
      =============================
      00:00:02.9246678
      00:00:04.6961790
      效率比1.605714
      =============================
      00:00:03.3911521
      00:00:05.5018374
      效率比1.62241
      =============================
      00:00:03.8737490
      00:00:06.2716150
      效率比1.619004
      =============================
      00:00:04.4047347
      00:00:07.1796579
      效率比1.629986
      =============================
      00:00:04.8688508
      00:00:07.9477787
      效率比1.632372
      =============================

      發(fā)現(xiàn)添加數(shù)據(jù)之后,效率比進一步加大

      環(huán)境:vs2008,sql 2005

      總結(jié):根據(jù)測試結(jié)果來說,對于大規(guī)模高并發(fā)的數(shù)據(jù)庫操作(在這里是10次循環(huán),每次1000次讀取數(shù)據(jù)),我們應(yīng)該盡可能的避免使用數(shù)據(jù)庫函數(shù),而應(yīng)該將數(shù)據(jù)全部取出來,在程序中進行處理

      寫在最后的話:對于我的程序、代碼、思路等等一切的一切有不同見解者,歡迎留言討論。這是我的第一篇博客,希望大家多多支持,如有不足望海涵。

    posted on 2012-05-16 09:32 順其自然EVO 閱讀(280) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫

    <2012年5月>
    293012345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 4hu四虎免费影院www| 免费一级全黄少妇性色生活片| 国产精品免费看久久久| 亚洲乱码国产一区三区| 手机看片国产免费永久| 亚洲ⅴ国产v天堂a无码二区| 无码日韩精品一区二区三区免费 | 人妻丰满熟妇无码区免费| 亚洲成a人片77777老司机| 亚洲黄色片免费看| 2017亚洲男人天堂一| 国产在线98福利播放视频免费| 日韩久久无码免费毛片软件| 中文亚洲AV片在线观看不卡| 男人的天堂网免费网站| 久久夜色精品国产嚕嚕亚洲av| 国产黄色免费观看| 国产免费久久精品99久久| 日韩免费无砖专区2020狼| 亚洲一卡二卡三卡| 亚洲不卡无码av中文字幕| 最近中文字幕大全免费版在线| 亚洲性无码av在线| 中文亚洲AV片不卡在线观看| 91成人免费观看网站| 两个人日本免费完整版在线观看1| 亚洲第一成年人网站| 亚洲天堂中文字幕在线| 在线观看免费人成视频色9| 西西人体免费视频| 亚洲av乱码一区二区三区按摩| 亚洲欧洲国产日韩精品| 国产午夜亚洲不卡| 国产精品久久香蕉免费播放| 67194成手机免费观看| 久久国产精品免费| 18禁亚洲深夜福利人口| 97se亚洲国产综合自在线| 亚洲日本一区二区三区| 亚洲最大av无码网址| 免费精品国产自产拍观看|