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;
  • 新建测试项目 控制台 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}    行";
}

  • 测试效果

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

C# 大数据量 线程跑分页_第1张图片demo下载

你可能感兴趣的:(C#,c#)