最近开发一个SQL server大数据量统计系统的经验总结

项目介绍
政府一个业务系统,
使用范围全国
数据是区域还存储,最大地方,主业务表,一年有600万,工作流表,1年有几千万,迄今为至系统已经运行三年。
其它全国还有46个地点,数据也比较多
新开发系统主要功能,对业务系统的数据进行分析统计.


所以对性能要求比较高。

我们的简要方案。

建立中间表,通过DTS调度每天共步数据。
中间表设计原则
 记录数同原表一样,减少多表连接,保存运算好的值,如果记录修改,根据修改日志,重新计算中间值


增量同步数据(DTS)
 直接从每天的数据库更改日志读取记录,更新中间表,根据服务器空间程度合理调度DTS,减少数据同步时间。

对中间数据进行运算
 查询不作字段运行,所以运算在生成中间表的过程中已经计算

根据查询,优化索引设计
 根据数据查询特性,对where ,GROUP BY等操作字段进行索引设计,提高查询速度 

 优化数据类型
 大量采用Int提高查询、统计速度 

 优化中间表关键字
 采用Int,提高插入速度


数据文件优化设计,一个主要业务,一个数据文件,建数据文件时,估计数据量,一次建一个比较大的文件,这样所分配的文件就是一个连续文件块,


sql server设置区别大小写。初始内存调到一个比较大的内存。



使用我们的Toolkit开发简单分页,相关压力测试,
 测试服务器配制
 2个至强3.0CPU
 2G内存
 150G硬盘
 Window 2000 Advance Server中文版+SP4
 测试数据ENTRY_WORKFLOW表,数据量2,473,437



 页数  界面显示时间  CPU  Reads I/O  Writes I/O  Duration
 第1页  2-3 S  642  10689  0 390
 第100页  3-4S  626  128001  0 423
  
 ....后页业数太多,没有必要




 压力测试

 并发数 平均每秒请求数 未字节响应毫秒数
 50 45.28 20,095.65
 25 45.41 10,043.12



索引优化测试, 

 对分量值小的数据建索引测试,测试语句,GROUP BY 分量值
  一个字段,大概有6个分量值,没有建索引,4S,建索引<1s
 两个分量,不建索引,3S,建索引,<1S
一般来说,对分量小的字段,不建索引,但是我们对性能要求太高,根据我们的测试,数据对分量范围小的也要建索引。

因为一个统计,有一个很多组合的WHERE,比如有十个指标这样会有十次访问原表,这样性能太低,所以我们把where后的数据作



用中间数据,
十个指标对中间数据作查询,中间数据,我们使用临时表,
经测试,10万条记录,插入操作,临时表需要,16s,表变量需要,40S




select ... into #temp from .......
速度极快,2,500,000条记录,16S


一个存储过程样例,有兴趣可以分析一下!

  1 None.gif SET  QUOTED_IDENTIFIER  ON  
  2 None.gif GO
  3 None.gif SET  ANSI_NULLS  ON  
  4 None.gif GO
  5 None.gif
  6 None.gif
  7 None.gif
  8 None.gif
  9 None.gif
 10 None.gif ALTER       Procedure  sp_tg009
 11 ExpandedBlockStart.gifContractedBlock.gif     /**/ /* Param List */
 12 ExpandedBlockStart.gifContractedBlock.gif     @TE_I_E_FLAG   varchar ( 4 ), /**/ /*进出口方式*/
 13 ExpandedBlockStart.gifContractedBlock.gif     @TE_PASS_RANGE   varchar ( 4 ), /**/ /*关区范围*/
 14 ExpandedBlockStart.gifContractedBlock.gif     @TE_C_OUTPUT   varchar ( 4 ), /**/ /*输出方式退单理由输出、申报单位输出、全部输出*/
 15 ExpandedBlockStart.gifContractedBlock.gif     @TE_END_DATE   datetime , /**/ /**********申报起止日期********/
 16 ExpandedBlockStart.gifContractedBlock.gif     @TE_END_DATEEND   datetime , /**/ /*************************/
 17 ExpandedBlockStart.gifContractedBlock.gif     @TE_MONI_T   varchar ( 4 ), /**/ /*监控类型*/
 18 None.gif     @USER_ID   varchar ( 64 ),
 19 None.gif     @CUSTOMER_CODE   varchar ( 4 ),
 20 None.gif     @PAGE_NUMBER   int ,
 21 None.gif     @TOTAL_COUNT   int  OUTPUT
 22 None.gif AS
 23 None.gif
 24 ExpandedBlockStart.gifContractedBlock.gif /**/ /******************************************************************************
 25InBlock.gif**        File: 
 26InBlock.gif**        Name: sp_tg009
 27InBlock.gif**        Desc: 通关业务监控-通关规范监控-报关单退(拒)单管理
 28InBlock.gif**
 29InBlock.gif**        This template can be customized:
 30InBlock.gif**              
 31InBlock.gif**        Return values:
 32InBlock.gif** 
 33InBlock.gif**        Called by: 
 34InBlock.gif**              
 35InBlock.gif**        Parameters:
 36InBlock.gif**        Input                            Output
 37InBlock.gif**     ----------                            -----------
 38InBlock.gif**        
 39InBlock.gif**        Auth: chengdj
 40InBlock.gif**        Date: 2005-4-7
 41InBlock.gif*******************************************************************************
 42InBlock.gif**        Change History
 43InBlock.gif*******************************************************************************
 44InBlock.gif**        Date:        Author:                Description:
 45InBlock.gif**        --------    --------        -------------------------------------------
 46InBlock.gif**    2005-04-11    chengdj                add HgDiv function
 47InBlock.gif**      2005-04-11    chengdj                
 48ExpandedBlockEnd.gif*******************************************************************************/

 49 None.gif SET  NOCOUNT  ON
 50 None.gif
 51 None.gif declare   @sqlWhere   varchar ( 4000 )
 52 None.gif set   @sqlWhere   =   ''
 53 None.gif
 54 None.gif set   @TE_END_DATEEND   =   DATEADD ( Day , 1 , @TE_END_DATEEND )     -- 结束日期加一天    
 55 None.gif set   @sqlWhere   =   @sqlWhere   +   '  TE_END_DATE  >=  ''' +   CONVERT ( varchar ( 20 ), @TE_END_DATE + '''  and TE_END_DATE <  ''' + CONVERT ( varchar ( 20 ), @TE_END_DATEEND ) + ''''
 56 None.gif
 57 None.gif if   @TE_I_E_FLAG   <>   ' -2 '          -- --进出口
 58 None.gif      set   @sqlWhere   =   @sqlWhere   +   '  and TE_I_E_FLAG =  ''' + @TE_I_E_FLAG + ''''
 59 None.gif
 60 None.gif if   @TE_PASS_RANGE   <>   ' -2 '          -- 关区范围
 61 None.gif          set   @sqlWhere   =   @sqlWhere   +   '  and TE_PASS_RANGE  in ( SELECT a.GCL_CODE
 62 None.gifFROM GL_CUSTOMER_LIST a CROSS JOIN
 63 None.gif      GL_CUSTOMER_LIST b
 64 None.gifWHERE (a.GCL_LAYER LIKE b.GCL_LAYER +  '' % '' ) AND (b.GCL_CODE =  ''' + @TE_PASS_RANGE + ''' ))  '
 65 None.gif
 66 ExpandedBlockStart.gifContractedBlock.gif /**/ /* if @TE_C_OUTPUT<> '-2'        --输出方式
 67InBlock.gif    set @sqlWhere = @sqlWhere + 'and '
 68ExpandedBlockEnd.gif****************监控类型**********************/

 69 None.gif
 70 ExpandedBlockStart.gifContractedBlock.gif     /**/ /*if @TE_MONI_T <> '-2'    --监控类型
 71InBlock.gif        if @TE_MONI_T = '2'
 72InBlock.gif                 set @sqlWhere = @sqlWhere + ' AND  TE_SCENE_FLAG = 1 '
 73InBlock.gif        else
 74ExpandedBlockEnd.gif                set @sqlWhere = @sqlWhere + ' AND  TE_WORKER_FLAG  =  ' +@TE_MONI_T + ' '*/

 75 ExpandedBlockStart.gifContractedBlock.gif /**/ /*
 76InBlock.gifCREATE TABLE #TG009(            
 77InBlock.gif        TE_PASS_RANGE VARCHAR(4) PRIMARY KEY NOT NULL,
 78InBlock.gif        MAN_CLE_COUNT int null,            --人工退单报关单总数
 79InBlock.gif        MAN_CLE_TOTAL int null,            --人工退单报关单总数
 80InBlock.gif        MAN_CLE_PCT float null,            --人工退单率
 81InBlock.gif        ELC_CLE_COUNT int null,            --电子退单总数
 82InBlock.gif        ELC_CLE_TOTAL int null,            --电子退单总次数
 83InBlock.gif        MAN_MU_COUNT int null,            --多次人工退单报关单数
 84InBlock.gif        ELC_CLE_PCT float null,            --电子退单率--
 85InBlock.gif        RE_COUNT int null,                --现场拒单报关单总数--
 86InBlock.gif        RE_TOTAL int null,                --现场拒单报关单总次数--
 87InBlock.gif        RE_PCT float null,                --现场拒单报关单率--
 88InBlock.gif        MU_ELC_CEL_EXP float null,        --多次电子退单指数
 89InBlock.gif        MU_MAN_EXP float null,            --多次人工退单指数
 90InBlock.gif        MU_SEC_EXP float null            --多次现场拒单指数
 91InBlock.gif)
 92ExpandedBlockEnd.gif    */

 93 None.gif     declare   @sql   varchar ( 8000 )
 94 None.gif     declare   @groupby   varchar ( 50 )
 95 None.gif    
 96 None.gif     if   @TE_C_OUTPUT    =   ' 1 '      -- 按申报单位
 97 None.gif           set   @groupby   =   ' TE_AGENT_CODE '
 98 None.gif     else                          -- 其它按关区
 99 None.gif           set   @groupby   =   ' TE_PASS_RANGE '
100 None.gif         
101 None.gif          declare   @sql2   nvarchar ( 500 )
102 None.gif            set   @sql2   =   ' select @COUNT = count(distinct( ' + @groupby + ' )) from TG_ENTRY where  ' + @sqlWhere
103 None.gif     execute  sp_executesql 
104 None.gif           @sql2 ,
105 None.gif          N ' @COUNT int output ' ,
106 None.gif           @TOTAL_COUNT  output
107 None.gif          
108 None.gif DECLARE   @START_ID   INT
109 None.gif DECLARE   @END_ID   INT
110 None.gif SET   @START_ID   =  ( @PAGE_NUMBER   -   1 *   15   +   1
111 None.gif SET   @END_ID   =   @PAGE_NUMBER   *   15
112 None.gif     
113 None.gif      -- --
114 None.gif       -- --
115 None.gif       -- ---     
116 None.gif       if   @TE_MONI_T   =   ' 1 '      -- 人工退单
117 None.gif                              set   @sql   =   '
118 None.gif                    select top  ' + convert ( varchar ( 20 ), @END_ID ) +   '   ' +   @groupby   + ' ,IDENTITY(int,1,1) AS TID into #PAGE  from TG_ENTRY where  ' + @sqlWhere   + '  group by  ' + @groupby +   ' ;
119 None.gif                    CREATE TABLE #TG009(            
120 None.gif                         ' +   @groupby + '  VARCHAR(10) PRIMARY KEY NOT NULL,
121 None.gif                        MAN_CLE_COUNT int null,    
122 None.gif                        MAN_CLE_TOTAL int null,
123 None.gif                        MAN_CLE_PCT numeric(10,2) null,
124 None.gif                        MU_MAN_EXP numeric(10,2) null,
125 None.gif                        MAN_CLE_TOTAL1 int null,
126 None.gif                        MAN_CLE_TOTAL2 int null,
127 None.gif                        MAN_CLE_TOTAL3 int null
128 None.gif                        );
129 None.gif
130 None.gif                    SELECT  ' +   @groupby + ' ,TE_CANCEL_FLAG,TE_WORKER_FLAG,TE_END_FLAG,TE_CANCEL_TIME INTO #temp1 FROM TG_ENTRY where ' + @sqlWhere + '  AND  ' + @groupby + '  in ( select   ' +   @groupby   + '  from #PAGE where TID between  ' +   convert ( varchar ( 20 ), @START_ID ) +   '  AND  ' +   convert ( varchar ( 20 ), @END_ID ) + ' );
131 None.gif                    INSERT INTO #TG009(
132 None.gif                             ' +   @groupby + ' ,
133 None.gif                            MAN_CLE_COUNT,
134 None.gif                            MAN_CLE_TOTAL,
135 None.gif                            MAN_CLE_PCT,
136 None.gif                            MU_MAN_EXP,
137 None.gif                            MAN_CLE_TOTAL1,
138 None.gif                            MAN_CLE_TOTAL2,
139 None.gif                            MAN_CLE_TOTAL3) 
140 None.gif                    SELECT a. ' +   @groupby + ' ,
141 None.gif                    (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
142 None.gif                    (SELECT SUM(TE_CANCEL_TIME) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
143 None.gif                    risk.HgDiv((SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_END_FLAG = 1 AND TE_WORKER_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
144 None.gif                    risk.HgDiv((SELECT SUM(TE_CANCEL_TIME) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0  and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0  and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
145 None.gif                    (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 AND TE_CANCEL_TIME = 1 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
146 None.gif                    (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 AND TE_CANCEL_TIME = 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
147 None.gif                    (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 1 AND TE_CANCEL_TIME > 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' )
148 None.gif                    from #temp1 a
149 None.gif                    group by a. ' +   @groupby + ' ;
150 None.gif                    DROP TABLE #temp1;
151 None.gif                    SELECT * FROM #TG009;
152 None.gif                    DROP TABLE #TG009 '
153 None.gif     else   if          @TE_MONI_T   =   ' 0 '      -- 电子
154 None.gif                  set   @sql   =   '
155 None.gif                select top  ' + convert ( varchar ( 20 ), @END_ID ) +   '   ' +   @groupby   + ' ,IDENTITY(int,1,1) AS TID into #PAGE  from TG_ENTRY where  ' + @sqlWhere   + '  group by  ' + @groupby +   ' ;
156 None.gif                CREATE TABLE #TG009(            
157 None.gif                     ' +   @groupby + '  VARCHAR(10) PRIMARY KEY NOT NULL,
158 None.gif                    ELC_CLE_COUNT int null,
159 None.gif                    ELC_CLE_TOTAL int null,
160 None.gif                    ELC_CLE_PCT numeric(10,2)  null,
161 None.gif                    MU_ELC_CEL_EXP numeric(10,2) null,
162 None.gif                    ELC_CLE_COUNT1 int null,
163 None.gif                    ELC_CLE_COUNT2 int null,
164 None.gif                    ELC_CLE_COUNT2B int null
165 None.gif                );
166 None.gif                SELECT  ' +   @groupby + ' ,TE_CANCEL_FLAG,TE_WORKER_FLAG,TE_END_FLAG,TE_CANCEL_TIME INTO #temp1 FROM TG_ENTRY where ' + @sqlWhere + '  AND  ' + @groupby + '  in ( select   ' +   @groupby   + '  from #PAGE where TID between  ' +   convert ( varchar ( 20 ), @START_ID ) +   '  AND  ' +   convert ( varchar ( 20 ), @END_ID ) + ' );
167 None.gif                INSERT INTO #TG009(
168 None.gif                         ' +   @groupby + ' ,
169 None.gif                        ELC_CLE_COUNT,
170 None.gif                        ELC_CLE_TOTAL,
171 None.gif                        ELC_CLE_PCT,
172 None.gif                        MU_ELC_CEL_EXP,
173 None.gif                        ELC_CLE_COUNT1,
174 None.gif                        ELC_CLE_COUNT2,
175 None.gif                        ELC_CLE_COUNT2B) 
176 None.gif                SELECT a. ' +   @groupby + ' ,
177 None.gif                (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
178 None.gif                                (SELECT SUM(TE_CANCEL_TIME) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
179 None.gif                                risk.HgDiv((SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_END_FLAG = 1 AND TE_WORKER_FLAG = 0 and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
180 None.gif                                risk.HgDiv((SELECT SUM(TE_CANCEL_TIME) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0  and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0  and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
181 None.gif                                (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 AND TE_CANCEL_TIME = 1 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
182 None.gif                                (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 AND TE_CANCEL_TIME = 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
183 None.gif                                (SELECT COUNT(*) FROM #temp1 WHERE TE_CANCEL_FLAG = 1 AND TE_WORKER_FLAG = 0 AND TE_CANCEL_TIME > 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' )
184 None.gif                from #temp1 a
185 None.gif                group by a. ' +   @groupby + ' ;
186 None.gif                DROP TABLE #temp1;
187 None.gif                SELECT * FROM #TG009;
188 None.gif                DROP TABLE #TG009 '
189 None.gif        
190 None.gif     else   if          @TE_MONI_T   =   ' 2 '      -- 现场拒单
191 None.gif              set   @sql   =   '
192 None.gif            select top  ' + convert ( varchar ( 20 ), @END_ID ) +   '   ' +   @groupby   + ' ,IDENTITY(int,1,1) AS TID into #PAGE  from TG_ENTRY where  ' + @sqlWhere   + '  group by  ' + @groupby +   ' ;
193 None.gif            CREATE TABLE #TG009(            
194 None.gif                 ' +   @groupby + '  VARCHAR(10) PRIMARY KEY NOT NULL,
195 None.gif                RE_COUNT int null,
196 None.gif                RE_TOTAL int null,
197 None.gif                RE_PCT numeric(10,2) null,
198 None.gif                MU_SEC_EXP numeric(10,2) null,
199 None.gif                RE_TOTAL1  int null,
200 None.gif                RE_TOTAL2  int null,
201 None.gif                RE_TOTAL2B  int null
202 None.gif            );
203 None.gif            SELECT  ' +   @groupby + ' ,TE_SCENE_TIME,TE_CANCEL_FLAG,TE_SCENE_FLAG,TE_MEET_FLAG INTO #temp1 FROM TG_ENTRY where ' + @sqlWhere + '  AND  ' + @groupby + '  in ( select   ' +   @groupby   + '  from #PAGE where TID between  ' +   convert ( varchar ( 20 ), @START_ID ) +   '  AND  ' +   convert ( varchar ( 20 ), @END_ID ) + ' );
204 None.gif            INSERT INTO #TG009(
205 None.gif                     ' +   @groupby + ' ,
206 None.gif                    RE_COUNT,
207 None.gif                    RE_TOTAL,
208 None.gif                    RE_PCT,
209 None.gif                    MU_SEC_EXP,
210 None.gif                    RE_TOTAL1,
211 None.gif                    RE_TOTAL2,
212 None.gif                    RE_TOTAL2B) 
213 None.gif            SELECT a. ' +   @groupby + ' ,
214 None.gif            (SELECT COUNT(*) FROM #temp1 WHERE TE_SCENE_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
215 None.gif            (SELECT SUM(TE_SCENE_TIME) FROM #temp1 WHERE TE_SCENE_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),
216 None.gif            risk.HgDiv((SELECT SUM(TE_SCENE_TIME) FROM #temp1 WHERE TE_SCENE_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_MEET_FLAG = 1 and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
217 None.gif            risk.HgDiv((SELECT SUM(TE_SCENE_TIME) FROM #temp1 WHERE TE_SCENE_FLAG = 1  and  ' +   @groupby + '  =a. ' +   @groupby + ' ),(SELECT COUNT(*) FROM #temp1 WHERE TE_SCENE_FLAG = 1  and  ' +   @groupby + '  =a. ' +   @groupby + ' )),
218 None.gif            (SELECT COUNT(*) FROM #temp1 WHERE TE_SCENE_FLAG = 1 AND TE_SCENE_TIME = 1 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
219 None.gif            (SELECT COUNT(*) FROM #temp1 WHERE TE_SCENE_FLAG = 1 AND TE_SCENE_TIME = 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' ),
220 None.gif            (SELECT COUNT(*) FROM #temp1 WHERE TE_SCENE_FLAG = 1 AND TE_SCENE_TIME > 2 AND  ' +   @groupby + '  =a. ' +   @groupby + ' )
221 None.gif            from #temp1 a
222 None.gif            group by a. ' +   @groupby + ' ;
223 None.gif            DROP TABLE #temp1;
224 None.gif            SELECT * FROM #TG009;
225 None.gif            DROP TABLE #TG009 '
226 None.gif -- print @sql
227 None.gif
228 None.gif exec ( @sql )
229 None.gif
230 None.gif
231 None.gif
232 None.gif
233 None.gif
234 None.gif
235 None.gif SET  NOCOUNT  OFF
236 None.gif
237 None.gif
238 None.gif
239 None.gif
240 None.gif
241 None.gif GO
242 None.gif SET  QUOTED_IDENTIFIER  OFF  
243 None.gif GO
244 None.gif SET  ANSI_NULLS  ON  
245 None.gif GO
246 None.gif
247 None.gif


中间表生成SQL,以后提供,

另!
sql源代码管理,使用VS。NET,数据库项目就可以与SOURCE SAFE一起管理了,并且支持单步调试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值