[搜片神器]BT管理程序數據庫速度調試優化問題


DHT抓取程序開源地址:https://github.com/h31h31/H31DHTDEMO

數據處理程序開源地址:https://github.com/h31h31/H31DHTMgr

服務器在抓取和處理同時進行,所以訪問速度慢是有些的,特別是搜索速度通過SQL的like來查詢慢,正在通過分詞改進中。。

 ---------------------------------------------------------------------------------------------------

當數據庫里面很多表的數據都有300萬左右,總文件大小有8G大小的時候,發現新增加的數據速度比原來慢很多的問題,一些性能和速度優化的問題就必須進行考慮了.

因為服務器還需要跑網站,查詢速度與程序插入速度會導致人多會越來越慢.

 

1.目前數據操作流程是通過HASH值查詢數據庫里面是否,如果沒有,則直接插入,如果有,則直接更新此條紀錄的計數.

2.由於紀錄表采用ID與文件列表進行關聯.設置ID為主鍵值,只對hashkey進行了唯一鍵的約束索引設計,設計的表結構如圖所示:

3.沒有處理經驗之前,只有增加日志輸出信息.

[2013-9-5 23:55:02]: 2:2:線程[4]>>>>67F8DAC16B2ACB5CC79BDD02F7478457E99C5966更新到數據庫1010成功1TIME:0-78-0-140
[2013-9-5 23:55:02]: 2:2:線程[1]>>>>57D55712F097DFDA3F3204C3E35B59461CCFE851更新到數據庫1011成功1TIME:140-109-0-219
[2013-9-5 23:55:03]: 2:2:線程[3]>>>>720A898E7C76CD5AD0B7B379D3CD97329EC9BDFE更新到數據庫4011成功4TIME:0-422-0-16
[2013-9-5 23:55:03]: 2:2:線程[4]>>>>7B534EAFF508F861B8B1E5A5D79D9C11F1655B43更新到數據庫1011成功1TIME:0-78-16-31
[2013-9-5 23:55:03]: 2:2:線程[5]>>>>9AAF76DE08F2ACA7DEDD11B139EE76798591D30F更新到數據庫1011成功1TIME:0-485-0-31
[2013-9-5 23:55:03]: 2:2:線程[1]>>>>6D8C1ACA280773A40958A4D3B4FF5DA447651C14更新到數據庫1011成功1TIME:140-485-0-15
[2013-9-5 23:55:03]: 2:2:線程[2]>>>>6A511827CD07A9FB725AA9DF317DE180B342A4A4更新到數據庫1011成功1TIME:407-94-15-78
[2013-9-5 23:55:03]: 2:2:線程[4]>>>>95A6DAF234532E10012169372448096544D58D68更新到數據庫1011成功1TIME:0-94-0-109
[2013-9-5 23:55:03]: 2:2:線程[3]>>>>C0A3C675DE7848F19E1BACE2DFE729D825580290更新到數據庫3011成功3TIME:0-62-0-47
[2013-9-5 23:55:04]: 2:2:線程[5]>>>>DC82DDB68F6F5F0CB310726CD9A3A382A8549802更新到數據庫2010成功2TIME:0-31-0-16
[2013-9-5 23:55:04]: 2:2:線程[1]>>>>3CBB82952AA59A020388415B299AA79B46CCF7DF更新到數據庫1011成功1TIME:140-62-0-32
[2013-9-5 23:55:04]: 2:2:線程[4]>>>>BF59A4902E6424A84418239F7BE670CBBF84ED03更新到數據庫1010成功1TIME:0-47-0-110
[2013-9-5 23:55:04]: 2:2:線程[1]>>>>3A804B13102E6C5B427F7E1F0F472A88F64A225C更新到數據庫1011成功1TIME:140-78-0-16
[2013-9-5 23:55:04]: 2:2:線程[5]>>>>EBE9FD044F8A07FF8E157B98BF8BE10F6977A570更新到數據庫1010成功1TIME:0-94-0-93
[2013-9-5 23:55:04]: 2:2:線程[5]>>>>70CC8C9B5EDE1F5673B7A4B684219F39E75DB660更新到數據庫1011成功1TIME:0-31-0-32
[2013-9-5 23:55:05]: 2:2:線程[2]>>>>CAEAF85ED0D3A9DEA7DA2EC75445565368F51E63更新到數據庫6011成功6TIME:407-328-0-47

TIME:[讀取文本時間與此無關]-[查詢HASH存在否]-[更新紀錄計數值]-[寫入IP等信息到IP表]

平均的查詢hashkey的速度在100ms左右,還是比較費時的.而且SQLSERVER進程CPU占用經常在30%左右,到了必須需要考慮的問題了.

程序查詢語句:

string tempstr1 = string.Format("select top 1 ID,Detail from H31_DHT_TYPE_{0}_{1} where hashKey='{2}'", hashtype, isHanzhi, hashname);

目前發現查詢HASH是否存儲的時間比較大,如何進行優化呢?

 

從網上搜索數據庫優化經驗:

數據庫優化目標
1.避免磁盤I/O瓶頸、
2.減少CPU利用率
3.減少資源競爭。
角度:
基本表設計、擴展設計和數據庫表對象放置
方法:
1.數據庫設計
2.索引
3.避免長事務
4.存儲過程
5.sql優化。

1.開始分析的思路是否是在多表之間進行跳轉更新查詢,從而影響查詢速度?  

2.數據庫索引是否設置正確?如果將主索引移動到hashkey上是否可以?由於之前考慮自增的ID上進行主索引會方便很多,畢竟hashkey是40字節,索引起來會更慢的問題.

抱着試一下的態度,對hashkey設置主鍵,

 

設置后服務器上程序查詢速度增加了很快,統計信息如下:

[2013-9-6 0:50:43]: 2:2:線程[3]>>>>1EE9C3804EF32A5A6EA9ACA18948B426C44BC9CA更新到數據庫1011成功1TIME:0-15-0-16
[2013-9-6 0:50:43]: 2:2:線程[2]>>>>46E527F7CE92F958688F40CD30F4D068ECCF0BDC更新到數據庫1011成功1TIME:171-0-0-15
[2013-9-6 0:50:43]: 2:2:線程[1]>>>>F865CBCEA3D97F4D8706D8EEC5D1D2C3E5B93CDF更新到數據庫4010成功4TIME:0-47-0-31
[2013-9-6 0:50:43]: 2:2:線程[3]>>>>46F08974CB1861B5A18BDA403F12DF3BF72BD990更新到數據庫1011成功1TIME:0-0-0-16
[2013-9-6 0:50:43]: 2:2:線程[5]>>>>2E0CB6E4A3CAF3DF42FE063DAA4C0B2DED0E393A更新到數據庫3011成功3TIME:0-31-16-31
[2013-9-6 0:50:43]: 2:2:線程[4]>>>>2889CAB940CD696A645868FACC3893774A1C6252更新到數據庫3010成功3TIME:15-47-0-31
[2013-9-6 0:50:43]: 2:2:線程[1]>>>>9DC1DE71F39C237B264EE8FDE618642F20F0610C更新到數據庫1011成功1TIME:0-0-0-32
[2013-9-6 0:50:43]: 2:2:線程[2]>>>>23710902E6EB72D8099ECF39CEFD6B17DF942AFC更新到數據庫1011成功1TIME:171-15-0-32
[2013-9-6 0:50:43]: 2:2:線程[3]>>>>4E8D7DA699BD577C2AA06B71D173049657067DB7更新到數據庫1011成功1TIME:0-0-0-16
[2013-9-6 0:50:44]: 2:2:線程[1]>>>>FD410EE7433B4796D611D2BF7F942029DFEEC0A9更新到數據庫1011成功1TIME:0-0-0-31
[2013-9-6 0:50:44]: 2:2:線程[5]>>>>B62136A52A711275BE375592B377DC8F28AB35A5更新到數據庫2011成功2TIME:0-62-16-16
[2013-9-6 0:50:44]: 2:2:線程[2]>>>>8DF4D76D34A8A352118F6D34F8017AF16EF30A80更新到數據庫2011成功2TIME:171-32-31-62
[2013-9-6 0:50:44]: 2:2:線程[4]>>>>353B7E166C071433DDDFB82928625D1D8E762204更新到數據庫1011成功1TIME:15-0-0-15
[2013-9-6 0:50:44]: 2:2:線程[3]>>>>511C7C32A4B0CA0F77853944FB9BD03DAC389579更新到數據庫1011成功1TIME:0-0-0-94
[2013-9-6 0:50:44]: 2:2:線程[1]>>>>562E5E0CDADD9ED787765C83DD6EA1508986E97C更新到數據庫1011成功1TIME:0-0-0-31
[2013-9-6 0:50:44]: 2:2:線程[2]>>>>3748B7734A277347F8206898B827BDE6DB4FD131更新到數據庫3011成功3TIME:171-31-0-31
[2013-9-6 0:50:44]: 2:2:線程[4]>>>>CFDB99C97C4EB6AF3B698DC3690FA9F8E35DD4B1更新到數據庫1011成功1TIME:15-0-0-94
[2013-9-6 0:50:44]: 2:2:線程[3]>>>>7D4CF91647D6268580CC7D9A525786B5F3F2D22E更新到數據庫1011成功1TIME:0-0-0-78

查詢hashkey是否存在的速度只需要10ms左右.這時候SQLSERVER的進程占用CPU速度在17%左右,基本上降了一半,但查詢速度快了10倍.

第一次數據庫優化成功,但插入IP信息列表的時間還占用比較大,需要進一步考慮如何優化的問題.特此記錄一下.

 

總結:

1.初期數據庫設計上比較充分的考慮到數據庫每張表的大小問題,所以表切分的問題目前不存在,需要考慮其它因素.

2.網上大部分介紹需要建立索引,如何建立對的索引很重要,以查詢的字段最好設置為主鍵值,因為涉汲到大量的查詢;

3.有時候問題並不是都是程序的問題,需要考慮的問題很多,比如數據庫,服務器內存,CPU等都需要考慮.

4.如果對很多字段進行比對的字段進行優化呢?比如需要比較時間和其它字段信息? 希望大家指導下此表是否有優化的余地,在此表示感謝

表結構:

CREATE TABLE [dbo].[H31_DHT_LOG_201307](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [hashID] [int] NOT NULL,
    [hashKey] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NULL,
    [recvTime] [datetime] NULL,
    [RecvIP] [nvarchar](16) COLLATE Chinese_PRC_CI_AS NULL,
    [recvPort] [int] NULL,
    [keyType] [int] NULL,
    [recvTimes] [int] NULL,
    [areaID] [int] NULL,
    [areaID2] [int] NULL,
 CONSTRAINT [PK_H31_DHT_LOG_201307] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

查詢到這一天的IP信息一條紀錄則更新計數:

StringBuilder strSql = new StringBuilder();
DateTime starttime = Convert.ToDateTime(thehash.updateTime.ToString("yyyy-MM-dd"));
DateTime endtime = starttime.AddDays(1);
int daytable = Convert.ToInt32((thehash.updateTime.Day - 1) / 5) + 1;

string tempstr1 = string.Format("select top 1 ID from H31_DHT_LOG_{0}_{1:D2} where hashKey='{2}' and RecvIP='{3}' and recvTime>='{4}' order by id desc", thehash.updateTime.ToString("yyyyMM"), daytable, thehash.hashKey, thehash.recvIp, starttime.ToString("yyyy-MM-dd"));
object countid = dbsql.ExecuteScalar(CommandType.Text, tempstr1.ToString(), null);
if (countid != null && dbsql.GetInt(countid) > 0)
{
    string tempstr = string.Format("update H31_DHT_LOG_{0}_{1:D2}  set recvTimes=recvTimes+1 where id={2}", thehash.updateTime.ToString("yyyyMM"), daytable,dbsql.GetInt(countid));
    strSql.Append(tempstr);
    return dbsql.ExecuteNonQuery(CommandType.Text, strSql.ToString(), null);
}

 

希望大家多多指導和推薦求助..

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM