• C# 大数据量 线程跑分页


    基本 了解C#中的Task任务

    C# 线程安全

    业务场景:
    当数据量达到一定量度,100w就会影响性能,如果达到500w-1kw (没有进行智能化分表储存)那查询一定是一个耗时耗力的慢查询

    解决:
    除了优化索引,优化表结构、优化查询语法
    1、智能化分表储存 ,如表A 存 1-200w 条 ;表B存 201w-400w 条;表C 存 401W-600w 条 (需要一些逻辑算法,其次取中间 数据比较麻烦)
    2、线程 + 分页查询

    • 新建表 插入600w条数据 16个字段栏位 ,模拟大表
    CREATE TABLE TEX
    (
        [Id] [INT] NOT NULL IDENTITY(1, 1),
        [UserName1] [VARCHAR](255) NOT NULL,
    	[UserName2] [VARCHAR](255) NOT NULL,
    	[UserName3] [VARCHAR](255) NOT NULL,
    	[UserName4] [VARCHAR](255) NOT NULL,
    	[UserName5] [VARCHAR](255) NOT NULL,
    	[UserName6] [VARCHAR](255) NOT NULL,
    	[UserName7] [VARCHAR](255) NOT NULL,
    	[UserName8] [VARCHAR](255) NOT NULL,
    	[UserName9] [VARCHAR](255) NOT NULL,
    	[UserName10] [VARCHAR](255) NOT NULL,
    	[UserName11] [VARCHAR](255) NOT NULL,
    	[UserName12] [VARCHAR](255) NOT NULL,
    	[UserName13] [VARCHAR](255) NOT NULL,
    	[UserName14] [VARCHAR](255) NOT NULL,
    	[UserName15] [VARCHAR](255) NOT NULL
    );
    ALTER TABLE dbo.TEX ADD CONSTRAINT PK_TEX_ID PRIMARY KEY(Id)
    DECLARE @Count INT =0;
    DECLARE @UserName VARCHAR(255)=CONVERT(VARCHAR(255),NEWID());
    WHILE @Count < 6000000
    BEGIN
        INSERT INTO dbo.TEX
        (
            UserName1,UserName2,UserName3,UserName4,UserName5,UserName6,UserName7,UserName8,
    		UserName9,UserName10,UserName11,UserName12,UserName13,UserName14,UserName15
        )
        VALUES
        (@UserName,@UserName,@UserName,@UserName,@UserName,@UserName,@UserName,@UserName,
    	 @UserName,@UserName,@UserName,@UserName,@UserName,@UserName,@UserName);
        SET @Count = @Count + 1;
    END;
    PRINT @Count;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 新建测试项目 控制台 demo

    为了方便测试使用dbhelper链接数据库类 项目里最好可以换成ef core 或者 sqlsugar 会更好

    static void Main(string[] args)
    {
       //程序启动时间
        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
        Taskt2();   //执行的线程
        Console.ReadKey();
    }
    
    ///执行的线程
    public static void Taskt2()
    {
        //为了方便dbhelper链接数据库类  项目里最好可以换成ef core 或者 sqlsugar 会更好 
        SQLServerDataBase dataBase = new SQLServerDataBase();  
        DataSet dataSet = new DataSet();
        var stus = dataBase.ExecuteNonDataSet("SELECT MAX(id) AS ID  FROM dbo.TEX", out dataSet); //获取总页数
    
        long suncount = Convert.ToInt64(dataSet.Tables[0].Rows[0]["ID"]);  //600w条数据    
        int pagesize = 500000;  //设置每页多少条
        double pagecount = Math.Ceiling(Convert.ToDouble(suncount / pagesize));  //总页数  有余数向上取整
    
        var blockingCollection = new BlockingCollection<string>(); // BlockingCollection 线程安全集合
        Task Taskproducer = Task.Factory.StartNew(() =>
        {
            for (int count = 1; count <= pagecount; count++)
            {
                blockingCollection.Add(count.ToString()); //添加分页页码
                Thread.Sleep(3500);
            }
            blockingCollection.CompleteAdding(); //添加完成
        });
    
        //多线程 执行 查询  
        Task[] taskArray = new Task[6];  //6个task任务
        for (int i = 0; i < taskArray.Length; i++)
        {
            taskArray[i] = Task.Factory.StartNew(() =>
            {
                foreach (string value in blockingCollection.GetConsumingEnumerable())
                {
                    string iResult = PageData(pagesize, Convert.ToInt32(value));
                    Console.WriteLine($@"Worker {Thread.CurrentThread.ManagedThreadId}: 
                    第{value}{iResult}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                }
            });
        }
        Task.WaitAll(taskArray); //设置等待
    }
    
    ///分页sql 
    ///如果是 ef core 或者 sqlsugar  这里最好用 linq 查询 返回list 
    public static string PageData(int PageSize,int CurrentPage)
    {
        SQLServerDataBase dataBase = new SQLServerDataBase();
        DataSet dataSet = new DataSet();
        string sql = $@"
        SELECT *
        FROM TEX
        ORDER BY Id 
        OFFSET ({PageSize} * ({CurrentPage} - 1)) ROW FETCH NEXT {PageSize} ROWS ONLY;";
        dataBase.ExecuteNonDataSet(sql, out dataSet);
        //获取每一页的第一个行和最后一行的id
        int min= Convert.ToInt32(dataSet.Tables[0].Rows[0]["Id"]);
        int max = Convert.ToInt32(dataSet.Tables[0].Rows[PageSize-1]["Id"]);
        return $@"查询: {min}{max}    行";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 测试效果

    Worker 4、7、5、9、10、11 对应的 Task[] taskArray = new Task[6]; //6个task任务

    在这里插入图片描述demo下载

  • 相关阅读:
    redis-springboot、分布式锁
    Shell 函数详解(函数定义、函数调用)
    【语音之家】AI产业沙龙—火山语音在AI视频译制方向的技术探索与实践
    葡萄糖-聚乙二醇-醛基/羟基 Glucose-PEG-CHO/OH
    win11-qt5.14配置
    灵活的IP网络测试工具——— X-Launch
    37基于MATLAB平台的图像去噪,锐化,边缘检测,程序已调试通过,可直接运行。
    多线程与高并发(8)—— 从CountDownLatch总结AQS共享锁(三周年打卡)
    尚硅谷Redis6从入门到精通
    【教程】IDEA操作GIT
  • 原文地址:https://blog.csdn.net/qq_38567182/article/details/125552236