posts - 3,  comments - 12,  trackbacks - 0
          SQL Server數據庫如下方法來優化查詢 :

            1、把數據、日志、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要.

            2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse)

            3、升級硬件

            4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用字節數小的列建索引好(參照索引的創建),不要對有限的幾個值的字段建單一索引如性別字段

            5、提高網速;

            6、擴大服務器的內存,Windows 2000和SQL server 2000能支持4-8G的內存。配置虛擬內存:虛擬內存大小應基于計算機上并發運行的服務進行配置。運行 Microsoft SQL Server? 2000 時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的 1.5 倍。如果另外安裝了全文檢索功能,并打算運行 Microsoft 搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的 3 倍。將 SQL Server max server memory 服務器配置選項配置為物理內存的 1.5 倍(虛擬內存大小設置的一半)。

            7、增加服務器 CPU個數;但是必須明白并行處理串行處理更需要資源例如內存。使用并行還是串行程是MsSQL自動評估選擇的。單個任務分解成多個任務,就可以在處理器上運行。例如耽擱查詢的排序、連接、掃描和GROUP BY字句同時執行,SQL SERVER根據系統的負載情況決定最優的并行等級,復雜的需要消耗大量的CPU的查詢最適合并行處理。但是更新操作Update,Insert, Delete還不能并行處理。

            8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。 like 'a%' 使用索引 like '%a' 不使用索引用 like '%a%' 查詢時,查詢耗時和字段值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對于字段的值很長的建全文索引。

            9、DB Server 和APPLication Server 分離;OLTP和OLAP分離

            10、分布式分區視圖可用于實現數據庫服務器聯合體。聯合體是一組分開管理的服務器,但它們相互協作分擔系統的處理負荷。這種通過分區數據形成數據庫服務器聯合體的機制能夠擴大一組服務器,以支持大型的多層 Web 站點的處理需要。有關更多信息,參見設計聯合數據庫服務器。(參照SQL幫助文件'分區視圖')

            a、在實現分區視圖之前,必須先水平分區表

            b、在創建成員表后,在每個成員服務器上定義一個分布式分區視圖,并且每個視圖具有相同的名稱。這樣,引用分布式分區視圖名的查詢可以在任何一個成員服務器上運行。系統操作如同每個成員服務器上都有一個原始表的復本一樣,但其實每個服務器上只有一個成員表和一個分布式分區視圖。數據的位置對應用程序是透明的。

            11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收縮數據和日志 DBCC SHRINKDB,DBCC SHRINKFILE. 設置自動收縮日志.對于大的數據庫不要設置數據庫自動增長,它會降低服務器的性能。在T-sql的寫法上有很大的講究,下面列出常見的要點:首先,DBMS處理查詢計劃的過程是這樣的:

            1、 查詢語句的詞法、語法檢查

            2、 將語句提交給DBMS的查詢優化器

            3、 優化器做代數優化和存取路徑的優化

            4、 由預編譯模塊生成查詢規劃

            5、 然后在合適的時間提交給系統處理執行

            6、 最后將執行結果返回給用戶其次,看一下SQL SERVER的數據存放的結構:一個頁面的大小為8K(8060)字節,8個頁面為一個盤區,按照B樹存放。

            12.commit和rollback的區別 Rollback:回滾所有的事物。 Commit:提交當前的事物. 沒有必要在動態SQL里寫事物,如果要寫請寫在外面如: begin tran exec(@s) commit trans 或者將動態SQL 寫成函數或者存儲過程。

            13、在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的數據,浪費了服務器的I/O資源,加重了網絡的負擔降低性能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯接訪問表,后果嚴重。

            14、SQL的注釋申明對執行沒有任何影響

            15、盡可能不使用光標,它占用大量的資源。如果需要row-by-row地執行,盡量采用非光標技術,如:在客戶端循環,用臨時表,Table變量,用子查詢,用Case語句等等。游標可以按照它所支持的提取選項進行分類: 只進 必須按照從第一行到最后一行的順序提取行。

          FETCH NEXT 是唯一允許的提取操作,也是默認方式??蓾L動性可以在游標中任何地方隨機提取任意行。游標的技術在SQL2000下變得功能很強大,他的目的是支持循環。有四個并發選項 READ_ONLY:不允許通過游標定位更新(Update),且在組成結果集的行中沒有鎖。 OPTIMISTIC WITH valueS:樂觀并發控制是事務控制理論的一個標準部分。樂觀并發控制用于這樣的情形,即在打開游標及更新行的間隔中,只有很小的機會讓第二個用戶更新某一行。當某個游標以此選項打開時,沒有鎖控制其中的行,這將有助于最大化其處理能力。如果用戶試圖修改某一行,則此行的當前值會與最后一次提取此行時獲取的值進行比較。如果任何值發生改變,則服務器就會知道其他人已更新了此行,并會返回一個錯誤。如果值是一樣的,服務器就執行修改。選擇這個并發選項OPTIMISTIC WITH ROW VERSIONING:此樂觀并發控制選項基于行版本控制。使用行版本控制,其中的表必須具有某種版本標識符,服務器可用它來確定該行在讀入游標后是否有所更改。在 SQL Server 中,這個性能由 timestamp 數據類型提供,它是一個二進制數字,表示數據庫中更改的相對順序。每個數據庫都有一個全局當前時間戳值:@@DBTS。每次以任何方式更改帶有 timestamp 列的行時,SQL Server 先在時間戳列中存儲當前的 @@DBTS 值,然后增加 @@DBTS 的值。如果某 個表具有 timestamp 列,則時間戳會被記到行級。服務器就可以比較某行的當前時間戳值和上次提取時所存儲的時間戳值,從而確定該行是否已更新。服務器不必比較所有列的值,只需比較 timestamp 列即可。如果應用程序對沒有 timestamp 列的表要求基于行版本控制的樂觀并發,則游標默認為基于數值的樂觀并發控制。 SCROLL LOCKS 這個選項實現悲觀并發控制。在悲觀并發控制中,在把數據庫的行讀入游標結果集時,應用程序將試圖鎖定數據庫行。在使用服務器游標時,將行讀入游標時會在其上放置一個更新鎖。如果在事務內打開游標,則該事務更新鎖將一直保持到事務被提交或回滾;當提取下一行時,將除去游標鎖。如果在事務外打開游標,則提取下一行時,鎖就被丟棄。因此,每當用戶需要完全的悲觀并發控制時,游標都應在事務內打開。更新鎖將阻止任何其它任務獲取更新鎖或排它鎖,從而阻止其它任務更新該行。然而,更新鎖并不阻止共享鎖,所以它不會阻止其它任務讀取行,除非第二個任務也在要求帶更新鎖的讀取。滾動鎖根據在游標定義的 Select 語句中指定的鎖提示,這些游標并發選項可以生成滾動鎖。滾動鎖在提取時在每行上獲取,并保持到下次提取或者游標關閉,以先發生者為準。下次提取時,服務器為新提取中的行獲取滾動鎖,并釋放上次提取中行的滾動鎖。滾動鎖獨立于事務鎖,并可以保持到一個提交或回滾操作之后。如果提交時關閉游標的選項為關,則 COMMIT 語句并不關閉任何打開的游標,而且滾動鎖被保留到提交之后,以維護對所提取數據的隔離。所獲取滾動鎖的類型取決于游標并發選項和游標 Select 語句中的鎖提示。鎖提示 只讀 樂觀數值 樂觀行版本控制 鎖定無提示 未鎖定 未鎖定 未鎖定 更新 NOLOCK 未鎖定 未鎖定未鎖定 未鎖定 HOLDLOCK 共享 共享 共享 更新 UPDLOCK 錯誤 更新 更新 更新 TABLOCKX 錯誤 未鎖定 未鎖定更新其它 未鎖定 未鎖定 未鎖定 更新 *指定 NOLOCK 提示將使指定了該提示的表在游標內是只讀的。


            16、用Profiler來跟蹤查詢,得到查詢所需的時間,找出SQL的問題所在;用索引優化器優化索引

            17、注意UNion和UNion all 的區別。UNION all好

            18、注意使用DISTINCT,在沒有必要時不要用,它同UNION一樣會使查詢變慢。重復的記錄在查詢里是沒有問題的

            19、查詢時不要返回不需要的行、列

            20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT來限制查詢消耗的資源。當評估查詢消耗的資源超出限制時,服務器自動取消查詢,在查詢之前就扼殺掉。 SET LOCKTIME設置鎖的時間

            21、用select top 100 / 10 Percent 來限制用戶返回的行數或者SET ROWCOUNT來限制操作的行

            22、在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE '%500'",因為他們不走索引全是表掃描。也不要在Where字句中的列名加函數,如Convert,substring等,如果必須用函數的時候,創建計算列再創建索引來替代.還可以變通寫法:Where SUBSTRING(firstname,1,1) = 'm'改為Where firstname like 'm%'(索引掃描),一定要將函數和列名分開。并且索引不能建得太多和太大。NOT IN會多次掃描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER JOIN 來替代,特別是左連接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,現在2000的優化器能夠處理了。相同的是IS NULL,"NOT", "NOT EXISTS", "NOT IN"能優化她,而"<>"等還是不能優化,用不到索引。

            23、使用Query Analyzer,查看SQL語句的查詢計劃和評估分析是否是優化的SQL。一般的20%的代碼占據了80%的資源,嚴重優化的重點是這些慢的地方。

            24、如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引: Select * FROM PersonMember (INDEX = IX_Title) Where processid IN ('男','女')

            25、將需要查詢的結果預先計算好放在表中,查詢的時候再Select。這在SQL7.0以前是最重要的手段。例如醫院的住院費計算。

            26、MIN() 和 MAX()能使用到合適的索引。

            27、數據庫有一個原則是代碼離數據越近越好,所以優先選擇Default,依次為Rules,Triggers, Constraint(約束如外健主健CheckUNIQUE……,數據類型的最大長度等等都是約束),Procedure.這樣不僅維護工作小,編寫程序質量高,并且執行的速度快。

            28、如果要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌Insert來插入(不知JAVA是否)。因為這樣應用程序首先將二進制值轉換成字符串(尺寸是它的兩倍),服務器受到字符后又將他轉換成二進制值.存儲過程就沒有這些動作: 方法:Create procedure p_insert as insert into table(Fimage) values (@image), 在前臺調用這個存儲過程傳入二進制參數,這樣處理速度明顯改善。

            29、Between在某些時候比IN 速度更快,Between能夠更快地根據索引找到范圍。用查詢優化器可見到差別。 select * from chineseresume where title in ('男','女') Select * from chineseresume where between '男' and '女' 是一樣的。由于in會在比較多次,所以有時會慢些。

           

           

            30、在必要是對全局或者局部臨時表創建索引,有時能夠提高速度,但不是一定會這樣,因為索引也耗費大量的資源。他的創建同是實際表一樣。

            31、不要建沒有作用的事物例如產生報表時,浪費資源。只有在必要使用事物時使用它。

            32、用OR的字句可以分解成多個查詢,并且通過UNION 連接多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到聯合索引,用UNION all執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。

            33、盡量少用視圖,它的效率低。對視圖操作比直接對表操作慢,可以用stored procedure來代替她。特別的是不要用視圖嵌套,嵌套視圖增加了尋找原始資料的難度。我們看視圖的本質:它是存放在服務器上的被優化好了的已經產生了查詢規劃的SQL。對單個表檢索數據時,不要使用指向多個表的視圖,直接從表檢索或者僅僅包含這個表的視圖上讀,否則增加了不必要的開銷,查詢受到干擾.為了加快視圖的查詢,MsSQL增加了視圖索引的功能。

            34、沒有必要時不要用DISTINCT和ORDER BY,這些動作可以改在客戶端執行。它們增加了額外的開銷。這同UNION 和UNION ALL一樣的道理。

               select top 20 ad.companyname,comid,position,ad.referenceid,worklocation, convert(varchar(10),ad.postDate,120) as postDate1,workyear,degreedescription FROM jobcn_query.dbo.COMPANYAD_query ad where referenceID in('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345',
          83 <!---->


            'JCNAD00333138','JCNAD00303570','JCNAD00303569',
            'JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933',
            'JCNAD00254567','JCNAD00254585','JCNAD00254608',
            'JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618',
            'JCNAD00279196','JCNAD00268613') order by postdate desc 

            35、在IN后面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最后面,減少判斷的次數。

            36、當用Select INTO時,它會鎖住系統表(sysobjects,sysindexes等等),阻塞其他的連接的存取。創建臨時表時用顯示申明語句,而不是 select INTO. drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ' --commit 在另一個連接中Select * from sysobjects可以看到 Select INTO 會鎖住系統表,Create table 也會鎖系統表(不管是臨時表還是系統表)。所以千萬不要在事物內使用它!!!這樣的話如果是經常要用的臨時表請使用實表,或者臨時表變量。

            37、一般在GROUP BY 個HAVING字句之前就能剔除多余的行,所以盡量不要用它們來做剔除行的工作。他們的執行順序應該如下最優:select 的Where字句選擇所有合適的行,Group By用來分組個統計行,Having字句用來剔除多余的分組。這樣Group By 個Having的開銷小,查詢快.對于大的數據行進行分組和Having十分消耗資源。如果Group BY的目的不包括計算,只是分組,那么用Distinct更快

            38、一次更新多條記錄比分多次更新每次一條快,就是說批處理好

            39、少用臨時表,盡量用結果集和Table類性的變量來代替它,Table 類型的變量比臨時表好

            40、在SQL2000下,計算字段是可以索引的,需要滿足的條件如下:

            a、計算字段的表達是確定的

            b、不能用在TEXT,Ntext,Image數據類型

            c、必須配制如下選項 ANSI_NULLS = ON, ANSI_PADDINGS = ON, …….

            41、盡量將數據的處理工作放在服務器上,減少網絡的開銷,如使用存儲過程。存儲過程是編譯好、優化過、并且被組織到一個執行規劃里、且存儲在數據庫中的SQL語句,是控制流語言的集合,速度當然快。反復執行的動態SQL,可以使用臨時存儲過程,該過程(臨時表)被放在Tempdb中。以前由于SQL SERVER對復雜的數學計算不支持,所以不得不將這個工作放在其他的層上而增加網絡的開銷。SQL2000支持UDFs,現在支持復雜的數學計算,函數的返回值不要太大,這樣的開銷很大。用戶自定義函數象光標一樣執行的消耗大量的資源,如果返回大的結果采用存儲過程

            42、不要在一句話里再三的使用相同的函數,浪費資源,將結果放在變量里再調用更快

            43、Select COUNT(*)的效率教低,盡量變通他的寫法,而EXISTS快.同時請注意區別: select count(Field of null) from Table 和 select count(Field of NOT null) from Table 的返回值是不同的!!!

            44、當服務器的內存夠多時,配制線程數量 = 最大連接數+5,這樣能發揮最大的效率;否則使用 配制線程數量<最大連接數啟用SQL SERVER的線程池來解決,如果還是數量 = 最大連接數+5,嚴重的損害服務器的性能。

            45、按照一定的次序來訪問你的表。如果你先鎖住表A,再鎖住表B,那么在所有的存儲過程中都要按照這個順序來鎖定它們。如果你(不經意的)某個存儲過程中先鎖定表B,再鎖定表A,這可能就會導致一個死鎖。如果鎖定順序沒有被預先詳細的設計好,死鎖很難被發現

            46、通過SQL Server Performance Monitor監視相應硬件的負載 Memory: Page Faults / sec計數器如果該值偶爾走高,表明當時有線程競爭內存。如果持續很高,則內存可能是瓶頸。

            Process:

            1、% DPC Time 指在范例間隔期間處理器用在緩延程序調用(DPC)接收和提供服務的百分比。(DPC 正在運行的為比標準間隔優先權低的間隔)。 由于 DPC 是以特權模式執行的,DPC 時間的百分比為特權時間百分比的一部分。這些時間單獨計算并且不屬于間隔計算總數的一部 分。這個總數顯示了作為實例時間百分比的平均忙時。

            2、%Processor Time計數器 如果該參數值持續超過95%,表明瓶頸是CPU??梢钥紤]增加一個處理器或換一個更快的處理器。

            3、% Privileged Time 指非閑置處理器時間用于特權模式的百分比。(特權模式是為操作系統組件和操縱硬件驅動程序而設計的一種處理模式。它允許直接訪問硬件和所有內存。另一種模式為用戶模式,它是一種為應用程序、環境分系統和整數分系統設計的一種有限處理模式。操作系統將應用程序線程轉換成特權模式以訪問操作系統服務)。特權時間的 % 包括為間斷和 DPC 提供服務的時間。特權時間比率高可能是由于失敗設備產生的大數量的間隔而引起的。這個計數器將平均忙時作為樣本時間的一部分顯示。

            4、% User Time表示耗費CPU的數據庫操作,如排序,執行aggregate functions等。如果該值很高,可考慮增加索引,盡量使用簡單的表聯接,水平分割大表格等方法來降低該值。 Physical Disk: Curretn Disk Queue Length計數器該值應不超過磁盤數的1.5~2倍。要提高性能,可增加磁盤。 SQLServer:Cache Hit Ratio計數器該值越高越好。如果持續低于80%,應考慮增加內存。 注意該參數值是從SQL Server啟動后,就一直累加記數,所以運行經過一段時間后,該值將不能反映系統當前值。
          84 <!---->


           47、分析select emp_name form employee where salary > 3000 在此語句中若salary是Float類型的,則優化器對其進行優化為Convert(float,3000),因為3000是個整數,我們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。同樣字符和整型數據的轉換。

           

           48、查詢的關聯同寫的順序

               select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' (A = B ,B = '號碼') 
            
            select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' and b.referenceid = 'JCNPRH39681' (A = B ,B = '號碼', A = '號碼') 
            
            select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID = 'JCNPRH39681' (B = '號碼', A = '號碼') 

            49、

            (1)IF 沒有輸入負責人代碼 THEN code1=0 code2=9999 ELSE code1=code2=負責人代碼 END IF 執行SQL語句為: Select 負責人名 FROM P2000 Where 負責人代碼>=:code1 AND負責人代碼 <=:code2

          <clk></clk>  (2)IF 沒有輸入負責人代碼 THEN  Select 負責人名 FROM P2000 ELSE code= 負責人代碼 Select 負責人代碼 FROM P2000 Where 負責人代碼=:code END IF 第一種方法只用了一條SQL語句,第二種方法用了兩條SQL語句。在沒有輸入負責人代碼時,第二種方法顯然比第一種方法執行效率高,因為它沒有限制條件; 在輸入了負責人代碼時,第二種方法仍然比第一種方法效率高,不僅是少了一個限制條件,還因相等運算是最快的查詢運算。我們寫程序不要怕麻煩

            50、關于JOBCN現在查詢分頁的新方法(如下),用性能優化器分析性能的瓶頸,如果在I/O或者網絡的速度上,如下的方法優化切實有效,如果在CPU或者內存上,用現在的方法更好。請區分如下的方法,說明索引越小越好。

               begin 
            
            DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20)) 
            
            insert into @local_variable (ReferenceID) 
            
            select top 100000 ReferenceID from chineseresume order by ReferenceID 
            
            select * from @local_variable where Fid > 40 and fid <= 60 
            
            end 和 
            
            begin 
            
            DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20)) 
            
            insert into @local_variable (ReferenceID) 
            
            select top 100000 ReferenceID from chineseresume order by updatedate 
            
            select * from @local_variable where Fid > 40 and fid <= 60 
            
            end 的不同 
            
            begin 
            
            create table #temp (FID int identity(1,1),ReferenceID varchar(20)) 
            
            insert into #temp (ReferenceID) 
            
            select top 100000 ReferenceID from chineseresume order by updatedate 
            
            select * from #temp where Fid > 40 and fid <= 60 drop table #temp 
            
            end 

           另附:存儲過程編寫經驗和優化措施 From:網頁教學網

            一、適合讀者對象:數據庫開發程序員,數據庫的數據量很多,涉及到對SP(存儲過程)的優化的項目開發人員,對數據庫有濃厚興趣的人。

            二、介紹:在數據庫的開發過程中,經常會遇到復雜的業務邏輯和對數據庫的操作,這個時候就會用SP來封裝數據庫操作。如果項目的SP較多,書寫又沒有一定的規范,將會影響以后的系統維護困難和大SP邏輯的難以理解,另外如果數據庫的數據量大或者項目對SP的性能要求很,就會遇到優化的問題,否則速度有可能很慢,經過親身經驗,一個經過優化過的SP要比一個性能差的SP的效率甚至高幾百倍。

            三、內容:

            1、開發人員如果用到其他庫的Table或View,務必在當前庫中建立View來實現跨庫操作,最好不要直接使用“databse.dbo.table_name”,因為sp_depends不能顯示出該SP所使用的跨庫table或view,不方便校驗。

            2、開發人員在提交SP前,必須已經使用set showplan on分析過查詢計劃,做過自身的查詢優化檢查。


            3、高程序運行效率,優化應用程序,在SP編寫過程中應該注意以下幾點:

            a)SQL的使用規范:

            i. 盡量避免大事務操作,慎用holdlock子句,提高系統并發能力。

            ii. 盡量避免反復訪問同一張或幾張表,尤其是數據量較大的表,可以考慮先根據條件提取數據到臨時表中,然后再做連接。

            iii. 盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該改寫;如果使用了游標,就要盡量避免在游標循環中再進行表連接的操作。

            iv. 注意where字句寫法,必須考慮語句順序,應該根據索引順序、范圍大小來確定條件子句的前后順序,盡可能的讓字段順序與索引順序相一致,范圍從大到小。

            v. 不要在where子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

            vi. 盡量使用exists代替select count(1)來判斷是否存在記錄,count函數只有在統計表中所有行數時使用,而且count(1)比count(*)更有效率。

            vii. 盡量使用“>=”,不要使用“>”。

            viii. 注意一些or子句和union子句之間的替換

            ix. 注意表之間連接的數據類型,避免不同類型數據之間的連接。

            x. 注意存儲過程中參數和數據類型的關系。

            xi. 注意insert、update操作的數據量,防止與其他應用沖突。如果數據量超過200個數據頁面(400k),那么系統將會進行鎖升級,頁級鎖會升級成表級鎖。

            b)索引的使用規范:

            i. 索引的創建要與應用結合考慮,建議大的OLTP表不要超過6個索引。

            ii. 盡可能的使用索引字段作為查詢條件,尤其是聚簇索引,必要時可以通過index index_name來強制指定索引

            iii. 避免對大表查詢時進行table scan,必要時考慮新建索引。

            iv. 在使用索引字段作為條件時,如果該索引是聯合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用。

            v. 要注意索引的維護,周期性重建索引,重新編譯存儲過程。

            c)tempdb的使用規范:

            i. 盡量避免使用distinct、order by、group by、having、join、cumpute,因為這些語句會加重tempdb的負擔。

            ii. 避免頻繁創建和刪除臨時表,減少系統表資源的消耗。

            iii. 在新建臨時表時,如果一次性插入數據量很大,那么可以使用select into代替create table,避免log,提高速度;如果數據量不大,為了緩和系統表的資源,建議先create table,然后insert。

            iv. 如果臨時表的數據量較大,需要建立索引,那么應該將創建臨時表和建立索引的過程放在單獨一個子存儲過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。

            v. 如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先truncate table,然后drop table,這樣可以避免系統表的較長時間鎖定。

            vi. 慎用大的臨時表與其他大表的連接查詢和修改,減低系統表負擔,因為這種操作會在一條語句中多次使用tempdb的系統表。

            d)合理的算法使用:

            根據上面已提到的SQL優化技術和ASE Tuning手冊中的SQL優化內容,結合實際應用,采用多種算法進行比較,以獲得消耗資源最少、效率最高的方法。具體可用ASE調優命令:set statistics io on, set statistics time on , set showplan on 等。 

          轉自:http://fableking.iteye.com/blog/360900

          posted @ 2011-08-13 12:41 [ 王志偉 ] 閱讀(285) | 評論 (0)編輯 收藏
          北京聯高軟件開發有限公司 徐斌 王春晨

          摘要:數據庫優化不僅是數據庫管理員的任務,程序員也必須知道一些優化技巧,有利于開發高效的數據庫系統。
          關鍵字:數據庫 優化 技巧

          如果是團隊開發,作為程序員必須知道本文描述的數據庫優化技巧,如果你的sa水平比較差,那即使你再努力也些不出高效的數據庫應用系統。
          如果是單獨開發,那就更不必說了。

          多數公司的數據庫管理員(sa)是不夠格的,即使拿了各種認證證件,也差不多還是垃圾管理員,無非是可以混個好職位,多拿一些工資。
          如果你所在的公司沒有合格的sa,作為程序員的你必須執行做許多數據庫優化的工作了。
          市面上的數據庫類圖書也不過是騙錢的把戲,無非為了出書而出書,為了出名而出書。
          95%以上的作者沒有實踐的經驗,99%以上的作者沒有優化的經驗。他們編寫圖書的來源無非是外文(不見得好?。┗蛘呤腔ヂ摼W上的資訊。

          廢話不說了,開始吧。程序員級別的優化有哪些手段?

          (1)數據庫的設置:如果你的數據庫記錄數不會超過30萬條?如果你的數據庫記錄超過100萬條?該如何設置數據庫?一個或多個?
          (2)數據庫表的設置:當你的某個數據庫表記錄超過100萬級別,而且每天大量增長,這是一個不得不考慮的問題。如果你的系統瀏覽量很大,即使是30萬條記錄也是需要考慮的。
          (3)索引的使用:索引可以大大提高數據庫訪問速度。什么時候用?哪些字段使用?
          (4)存儲過程的使用:存儲過程終歸是比較好的,但是如果需要維護成百上千的存儲過程,未必是劃算的工程。
          (5)高效的分頁技術:數據庫記錄分頁列表是大量必須使用的基本技術,怎樣的分頁是快速的?

          宗旨你需要從上述5個方面考慮數據庫的優化。

          什么時候需要數據庫優化?
          (1)編寫代碼之前;
          (2)系統速度慢了的時候;

          下面就是一些具體的優化技巧了。

          (1)超大量記錄數據庫的優化技巧

          如果你的數據庫表記錄有超過100萬級別,而且不斷增長中??梢圆扇蓚€手段:
          第一:將數據庫表拆分到不同的庫中,比如 tblMEMBER 就可以拆分到 DB1 與 DB2 中去。
          實際上,可以拆分到 DB001 ... DB100 甚至更多的庫中間去。
          DB1 與 DB2 最好不在一塊硬盤上。
          第二:如果更大量級的數據,則最好拆分到不同的數據庫服務器中去。

          數據庫的拆分帶來的是查詢等操作的復雜性。簡單地可以通過 hash 或者 按序號 匹配不同的數據庫。復雜一些,應該設置一個獨立的應用服務器(軟件)協調其中的操作。

          (2)中等量級數據庫的優化技巧

          所謂中等量級數據庫是指數據庫100萬-500萬條記錄左右(單個數據庫表)。這樣的數據庫為了提高訪問(響應)速度,可以將表拆分到更小的表。比如 tblMEMBER 可以拆分為 tblMEMBER_00 ... tblMEMBER_99 。
          這樣可以保證每個表的記錄數不超過50萬,那速度是"相當"快了。

          (3)避免使用視圖(viewport)與關聯

          視圖viewport與關聯都是為了程序員處理相對復雜的數據管理提供方便的手段。萬物有其利,必有其弊。視圖和關聯提高了編程效率,都會較大地影響數據庫的訪問效率(事實上并不像一般資料說介紹的的那樣高效),因此如果是web應用,則建議一般不要使用視圖與關聯。

          (4)不要忘記索引(index)也不要濫用索引(index)

          索引是提高數據庫效率的簡單又高效的方法。只要是設置了數據庫表(table),就不要忘記設置索引(index)。將索引設置在經常用于排序的字段上,其他字段就不要設置了。
          索引不是越多越好,也不是什么字段都適合建立索引的。數據重復性太多的字段不要設置索引。比如 tblMEMBER 的 iSex 字段只有 0 1 兩個值,就不要設置索引。

          (5)二進制的 text image 等字段應該單獨設置別的表中

          一般的數據庫應用難免都需要保存比如描述、圖片等信息;一般描述類信息用 text 字段,圖片類信息用 image 字段;這里要說的是,不要將這些字段與其他字段放在一個表中。
          比如:
           1tblMEMBER
           2id (int)
           3cName (varchar)(64)
           4cDescription (text)
           5bPhoto (image)
           6dDate (datetime)
           7就應該拆分為3個表
           8tblMEMBER
           9id (int)
          10cName (varchar)(64)
          11dDate (datetime)
          12tblMEMBER_DESC
          13id (int)
          14cDescription (text)
          15dDate (datetime)
          16tblMEMBER_PHOTO
          17id (int)
          18bPhoto (image)
          19dDate (datetime)
          20


          (6)不要使用文本類型的 id

          一般的數據庫表都會以一個種子字段作為主鍵??梢栽谂c不少年青的程序員朋友溝通過程中,發現他們很喜歡用字符串類型的作為系統的 id 號。
          比如:id = XX XX XX XX 這樣的字符串,每兩個位置代表不同的類別等含義。
          不知道是那本教材如此誤人子弟,作出這樣的表率 :<
          作為系統的 id 號,一定要使用數字型的。

          (7)數據庫表table的字段field不要太多

          本以為無需說明,也是發現不少的朋友,為了省事,一股腦把所有的相關字段都放在一個表中間。這樣做的后果便是,程序寫起來簡單了,運行效率下來了。
          無論字段多少,有兩類字段是必須獨立出去的:一是進程更新的字段,比如文章的點擊次數字段iShow,二是二進制或者是text字段;

          (8)將字符串(varchar)比較變成數字型(int)比較

          每個系統都會有用戶管理,其中必然有 昵稱,密碼,郵件等的字符串類型數據比較的問題。在數據庫操作中,字符串比較的效率是相當低下的。因此遇到字符串的比較,必須將其轉換為數字型比較。
          具體做法是:在數據庫表中增加相應的數字字段,比如 cNickname -> iNickNumber ,其中 iNickNumber 的數值為 cNickname 的 哈希值(如何計算字符串的哈希值?請參閱本站的其他文章)。
          通過這樣的轉換,系統效率可以提高 100 倍哦!??!

          (9)為每個數據庫表(table)設置 datetime 字段

          在許多情況下,很多的表是不需要 datetime 字段用于保存時間的。本文的建議是你應該為每個表都設置 datetime 字段,而且默認值為 getdate()。
          我們的經驗是,datetime 是實數,占用字節不多;在進行系統維護,遠程備份等環節都會發揮意想不到的效果。

          (10)適當使用存儲過程(Stored Processing)

          存儲過程(sp)已經被大大地宣傳了,本文也不例外地贊許采用存儲過程。本文的建議是只在下列情況才使用存儲過程:一是一個業務處理是事務,包含了多個處理過程;二是一種處理被高頻使用,使用存儲過程可以提高效率;

          (11)使用高效的分頁(ination)技術

          數據庫記錄分頁列表是大量必須使用的基本技術,因此本 文建議你在每個數據庫中建立下面的存儲過程:
           1CREATE PROCEDURE xsp_ination
           2(
           3@tblName   varchar(64),
           4@strGetFields varchar(256= "*",
           5@fldName varchar(64)="",
           6@PageSize   int = 20,
           7@PageIndex  int = 1,
           8@OrderType bit = 1,
           9@strWhere  varchar(256= ""
          10)
          11AS
          12BEGIN
          13declare @strSQL   varchar(1000)
          14declare @strTmp   varchar(110)
          15declare @strOrder varchar(400)
          16SET NOCOUNT ON
          17if @OrderType != 0
          18begin
          19set @strTmp = "&lt;(select min"
          20set @strOrder = " order by [" + @fldName +"] desc"
          21end
          22else
          23begin
          24set @strTmp = "&gt;(select max"
          25set @strOrder = " order by [" + @fldName +"] asc"
          26end
          27if @PageIndex = 1
          28begin
          29if @strWhere != ""
          30set @strSQL = "select top " + str(@PageSize+" "+@strGetFields+ "  from " + @tblName + " where " + @strWhere + " " + @strOrder
          31else
          32set @strSQL = "select top " + str(@PageSize+" "+@strGetFields+ "  from "+ @tblName + " "+ @strOrder
          33end
          34else
          35begin
          36set @strSQL = "select top " + str(@PageSize+" "+@strGetFields+ "  from "
          37+ @tblName + " where [" + @fldName + "]+ @strTmp + "(["+ @fldName + "]from (select top " + str((@PageIndex-1)*@PageSize+ " ["+ @fldName + "] from " + @tblName + " " + @strOrder + ") as tblTmp)"+ @strOrder
          38if @strWhere != ""
          39set @strSQL = "select top " + str(@PageSize+" "+@strGetFields+ "  from "
          40+ @tblName + " where [" + @fldName + "]+ @strTmp + "(["
          41+ @fldName + "]from (select top " + str((@PageIndex-1)*@PageSize+ " ["
          42+ @fldName + "] from " + @tblName + " where " + @strWhere + " "
          43+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
          44end
          45EXEC (@strSQL)
          46if @@error=0 return 1
          47SET NOCOUNT OFF
          48END
          49GO
          50


          使用方法是(C#):

          sql = "EXEC [dbo].[xsp_ination] \"tblNEWS\",\"*\",\"id\",40," + pindex.ToString() + ",1,\"iType=" + type.ToString();
          SqlDataReader sr = ExecuteReader(sql);
          while (sr.Read())
          {

          }

          sr.Close();



          上面的優化技巧僅是一些常見的手段,如果你的系統(小系統就算了)遇到效率問題,可以與聯高軟件聯系。

          轉載本文請注明出處,以便遇到優化困難的朋友可以找到聯高提供幫助。

          posted @ 2011-08-13 12:34 [ 王志偉 ] 閱讀(439) | 評論 (0)編輯 收藏

          千萬人同時訪問的網站,一般是有很多個數據庫同時工作,說明白一點就是數據庫集群和并發控制,這樣的網站實時性也是相對的。這些網站都有一些共同的特點:數據量大,在線人數多,并發請求多,pageview高,響應速度快??偨Y了一下各個大網站的架構,主要提高效率及穩定性的幾個地方包括:

          1、程序
          程序開發是一方面,系統架構設計(硬件+網絡+軟件)是另一方面。
          軟件架構方面,做網站首先需要很多web服務器存儲靜態資源,比如圖片、視頻、靜態頁等,千萬不要把靜態資源和應用服務器放在一起。
          一個好的程序員寫出來的程序會非常簡潔、性能很好,一個初級程序員可能會犯很多低級錯誤,這也是影響網站性能的原因之一。
          網站要做到效率高,不光是程序員的事情,數據庫優化、程序優化這是必須的,在性能優化上要數據庫和程序齊頭并進!緩存也是兩方面同時入手。第一,數據庫緩存和數據庫優化,這個由dba完成(而且這個有非常大的潛力可挖,只是由于我們都是程序員而忽略了他而已)。第二,程序上的優化,這個非常的有講究,比如說重要一點就是要規范SQL語句,少用in 多用or,多用preparestatement 存儲過程,另外避免程序冗余如查找數據少用雙重循環等。另外選用優秀的開源框架加以支持,我個人認為中后臺的支持是最最重要的,可以選取spring+ibatis。因為ibatis直接操作SQL并有緩存機制。spring的好處就不用我多說了,IOC的機制可以避免new對象,這樣也節省開銷。據我分析,絕大部分的開銷就是在NEW的時候和連接數據庫時候產生的,請盡量避免。另外可以用一些內存測試工具來做一個demo說明hibernate和ibatis誰更快!前臺你想用什么就用什么,struts,webwork都成,如果覺得自己挺牛X可以試試用tapestry。
          用數據庫也未必不能解決訪問量巨大所帶來的問題,作成靜態文件硬盤的尋址時間也未必少于數據庫的搜索時間,當然對資料的索引要下一翻工夫。我自己覺得門戶往往也就是當天、熱門的資料點擊率較高,將其做緩存最多也不過1~2G的數據量吧,舉個例子:

          ◎ 拿網易新聞來說http://news.163.com/07/0606/09/3GA0D10N00011229.html
          格式化一下,方便理解:http://域名/年/月日/新聞所屬分類/新聞ID.html
          可以把當天發布的、熱門的、瀏覽量大的作個緩存,用hashtable(key:年-月-日-分類-ID,value:新聞對象),靜態將其放到內存(速度絕對快過硬盤尋址靜態頁面)。

          通常是采用oracle存儲過程+2個weblogic,更新機制也幾乎一樣每簽發一條新聞,就會生成靜態頁面,然后發往前端的web服務器,前端的web都是做負載均衡的。另外還有定時程序,每5-15分鐘自動生成一次。在發布新聞的同時將數據緩存。當然緩存也不會越來越大,在個特定的時間段(如凌晨)刪除過期的數據。做一個大的網站遠沒有想象中那么簡單,服務器基本就要百十個的。
          這樣可以大大增加一臺計算機的處理速度,如果一臺機器處理不了,可以用httpserver集群來解決問題了。

          2、網絡
          中國的網絡分南電信和北網通,訪問的ip就要區分南北進入不同的網絡。

          3、集群
          通常會使用CDN與GSBL與DNS負載均衡技術,每個地區一組前臺服務器群,比如新浪和搜狐,而網易,百度使用了DNS負載均衡技術,每個頻道一組前臺服務器;一搜使用了DNS負載技術,所有頻道共用一組前臺服務器集群。
          網站使用基于Linux集群的負載均衡,失敗恢復,包括應用服務器和數據庫服務器,基于linux-ha的服務狀態檢測及高可用化。
          應用服務器集群可以采用apache+tomcat集群和weblogic集群等;web服務器集群可以用反向代理,也可以用NAT的方式,或者多域名解析都可以;Squid也可以,方法很多,可以根據情況選擇。

          4、數據庫
          因為是千萬人同時訪問的網站,所以一般是有很多個數據庫同時工作的,說明白一點就是數據庫集群和并發控制,數據分布到地理位置不同的數據中心,以免發生斷電事故。

          主流的數據庫有Sun的是MySQL和Oracle。
          Oracle是一款優秀的、廣泛采用的商業數據庫管理軟件。有很強大的功能和安全性,可以處理相對海量的數據。而MySQL是一款非常優秀的開源數據庫管理軟件,非常適合用多臺PC Server組成多點的存儲節點陣列(這里我所指的不是MySQL自身提供的集群功能),每單位的數據存儲成本也非常的低廉。用多臺PC Server安裝MySQL組成一個存儲節點陣列,通過MySQL自身的Replication或者應用自身的處理,可以很好的保證容錯(允許部分節點失效),保證應用的健壯性和可靠性??梢赃@么說,在關系數據庫管理系統的選擇上,可以考慮應用本身的情況來決定。

          MySQL數據庫服務器的master-slave模式,利用數據庫服務器在主從服務器間進行同步,應用只把數據寫到主服務器,而讀數據時則根據負載選擇一臺從服務器或者主服務器來讀取,將數據按不同策略劃分到不同的服務器(組)上,分散數據庫壓力。

          另外還有一點的是,那些網站的靜態化網頁并不是真的,而是通過動態網頁與靜態網頁網址交換所出現的假象,這可以用urlrewrite這樣的開源網址映射器實現。這樣的網站實時性也是相對的,因為在數據庫復制數據的時候有一個過程,一般在技術上可以用到hibernate和ecache,但是如果要使網站工作地更好,可以使用EJB和websphere,weblogic這樣大型的服務器來支持,并且要用oracle這樣的大型數據庫。
          大型門戶網站不建議使用Mysql數據庫,除非你對Mysql數據的優化非常熟悉。Mysql數據庫服務器的master-slave模式,利用數據庫服務器在主從服務器間進行同步,應用只把數據寫到主服務器,而讀數據時則根據負載選擇一臺從服務器或者主服務器來讀取,將數據按不同策略劃分到不同的服務器(組)上,分散數據庫壓力。
          大型網站要用oracle,數據方面操作盡量多用存儲過程,絕對提升性能;同時要讓DBA對數據庫進行優化,優化后的數據庫與沒優化的有天壤之別;同時還可以擴展分布式數據庫,以后這方面的研究會越來越多;

          5、頁面
          從開始就考慮使用虛擬存儲/簇文件系統。它能讓你大量并行IO訪問,而且不需要任何重組就能夠增加所需要的磁盤。
          頁面數據調用更要認真設計,一些數據查詢可以不通過數據庫的方式,實時性要求不高的可以使用lucene來實現,即使有實時性的要求也可以用lucene(基于Java的全文索引/檢索引擎),lucene+compass還是非常優秀的。
          新聞類的網站可以用靜態頁存儲,采用定時更新機制減輕服務器負擔;首頁每個小模塊可以使用oscache緩存,這樣不用每次都拉數據。
          前端的基于靜態頁面緩存的web加速器,主要應用有squid等。squid 將大部分靜態資源(圖片,js,css等)緩存起來,直接返回給訪問者,減少應用服務器的負載
          網站的靜態化網頁并不是真的,而是通過動態網頁與靜態網頁網址交換做出現的假象,這可以用urlrewrite這樣的開源網址映射器實現,后綴名為htm或者html并不能說明程序生成了靜態頁面,可能是通過url重寫來實現的,為的只不過是在搜索引擎中提升自己網站的覆蓋面積罷了。
          生成靜態頁面的服務器和www服務器是兩組不同的服務器,頁面生成后才會到www服務器,一部分數據庫并不是關系數據庫,這樣更適合信息衍生,www、mail服務器、路由器多,主要用負載平衡解決訪問瓶頸。
          ◎ 靜態頁面的缺點:
          1) 增加了程序的復雜度
          2) 不利于管理資料
          3) 速度不是最快
          4) 傷硬盤

          6、緩存
          從一開始就應該使用緩存,高速緩存是一個更好的地方存儲臨時數據,比如Web站點上跟蹤一個特定用戶的會話產生的臨時文件,就不再需要記錄到數據庫里。
          不能用lucene實現的可以用緩存,分布式緩存可以用memcached,如果有錢的話用10來臺機器做緩存,> 10G的存儲量相信存什么都夠了;如果沒錢的話可以在頁面緩存和數據緩存上下功夫,多用OSCACHE和EHCACHE,SWARMCACHE也可以,不過據說同步性不是很好;
          可以使用Memcache(分布式緩存)進行緩存,用大內存把這些不變的數據全都緩存起來,而當修改時就通知cache過期,memcache是LJ開發的一款分布式緩存產品,很多大型網站在應用,我們可以把Cache Server與App Server裝在一起。因為Cache Server對CPU消耗不大,而有了Cache Server的支援,App Server對內存要求也不是太高,所以可以和平共處,更有效的利用資源。

          單機內存緩存、文件緩存、數據庫緩存等的策略都是可以很簡單的實現的,例如可以使用微軟的Caching Application Block,但如何在集群環境中使多個緩存、多層緩存并保存同步是個重大問題。大型網站一般都使用緩存服務器群,并使用多層緩存。業內最常用的有:

          Squid cache,Squid服務器群,把它作為web服務器端前置cache服務器緩存相關請求來提高web服務器速度。Squid將大部分靜態資源(圖片,js,css等)緩存起來,直接返回給訪問者,減少應用服務器的負載

          memcache,memcache服務器群,一款分布式緩存產品,很多大型網站在應用; 它可以應對任意多個連接,使用非阻塞的網絡IO。由于它的工作機制是在內存中開辟一塊空間,然后建立一個HashTable,Memcached自管理這些HashTable。因為通常網站應用程序中最耗費時間的任務是數據在數據庫的檢索,而多個用戶查詢相同的SQL時,數據庫壓力會增大,而通過memcache的查詢緩存命中,數據直接從memcache內存中取,每次緩存命中將替換到數據庫服務器的一次往返,到達數據庫服務器的請求更少,間接地提高了數據庫服務器的性能,從而使應用程序運行得更快。它通過基于內存緩存對象來減少數據庫查詢的方式改善網站系統的反應,其最吸引人的一個特性就是支持分布式部署。有關memcache,以下文章可以參考:參考1,參考2,參考3官方站點

          e-Accelerator,比較特殊,PHP的緩存和加速器。是一個免費開源的PHP加速、優化、編譯和動態緩存的項目,它可以通過緩存PHP代碼編譯后的結果來提高PHP腳本的性能,使得一向很復雜和離我們很遠的 PHP腳本編譯問題完全得到解決。通過使用eAccelerator,可以優化你的PHP代碼執行速度,降低服務器負載,可以提高PHP應用執行速度最高達10倍。

           

          7、服務器操作系統與Web服務器
          最底層首先是操作系統。好的操作系統能提高好的性能、穩定性和安全性,而這些對大型網站的性能、安全性和穩定性都是至關重要的。

          • 淘寶網(阿里巴巴): Linux操作系統 + Web 服務器: Apache
          • 新浪:FreeBSD + Web 服務器:Apache
          • Yahoo:FreeBSD + Web 服務器:自己的
          • Google: 部分Linux + Web 服務器:自己的
          • 百度:Linux + Web 服務器: Apache
          • 網易:Linux + Web 服務器: Apache
          • eBay: Windows Server 2003/8 (大量) + Web 服務器:Microsoft IIS
          • MySpace: Windows Server 2003/8 + Web 服務器:Microsoft IIS

          由此可見,開源操作系統做Web應用是首選已經是一個既定事實。在開源操作系統中Linux和FreeBSD差不太多,很難說哪個一定比另外一個要優秀很多、能夠全面的超越對手,應該是各有所長。但熟悉Linux的技術人員更多些,利于系統管理、優化等,所以Linux使用更廣泛。而Windows Server和IIS雖然有的網站使用,但不開源,而且需要購買微軟的一系列應用產品,限制了其使用??傊_源操作系統,尤其是Linux做Web應用是首選已經是一個既定事實。
          常用的系統架構是:

          • Linux + Apache + PHP + MySQL
          • Linux + Apache + Java (WebSphere) + Oracle
          • Windows Server 2003/2008 + IIS + C#/ASP.NET + 數據庫

          以上一些不太成熟的想法,可以從某一個層次開始,逐步細化,把產品的性能指標提高上去。


          轉自:http://blog.sina.com.cn/s/blog_56fd58ab0100o2hw.html
          posted @ 2011-08-13 12:29 [ 王志偉 ] 閱讀(493) | 評論 (0)編輯 收藏
          以前在安裝sql的時候,如此提示,我只要重新啟動即可,可是今天重新啟動了N次計算機,問題卻絲毫沒有解決,依然提示這樣的話。“以前的某個程序安裝已在安裝計算機上創建掛起的文件操作。運行安裝程序之前必須重新啟動計算機。” 只好google以下,最終得知是安裝程序在先前的安裝過程中在系統注冊表留下某些信息,導致不能安裝。于是經過多次試,發現刪除掉如下鍵值信息即可安裝:
            在運行窗口輸入regedit,打開注冊表編輯器,在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\session Manager中找到PendingFileRenameOperations,刪除該鍵值(這個鍵值是安裝程序暫掛項目,只要找到對應的應用程序清除掉就行了),關閉注冊表編輯器。重新安裝SQL Server 2000即可。
                  特整理收藏與下,以便查找。
          資料引用:http://www.knowsky.com/340304.html
          posted @ 2011-07-03 22:23 [ 王志偉 ] 閱讀(188) | 評論 (0)編輯 收藏
          打開Sql Server 2000企業管理器時,顯示的錯誤狀態:

          MMC 不能打開文件 C:\Program Files\Microsoft SQL Server\80\Tools\BINN\SQL Server Enterprise Manager.MSC。

          分析:

          參看文件是否存在或被損壞。

          無論那種,先將其刪除

          然后,在運行框中輸入 mmc,打開控制臺

          執行以下三個步驟:

          1、控制臺--添加/刪除管理單元--添加--找到Microsoft SQL 企業管理器--添加--關閉--確定

          2、控制臺--選項--控制臺模式選擇"用戶模式完全訪問"--將下面的選擇全部取消

          3、控制臺--另存為--存儲為:C:\Program Files\Microsoft SQL Server\80\Tools\BINN\SQL Server Enterprise Manager.MSC

          在第三步時可能會遇到“無法保存”,這種現象。

          則在運行框中輸入 regsvr32 C:\Windows\system32\msxml3.dll

          然后再執行上面的第三步,即可

          參考:http://www.leezao.cn/article.asp?id=467
          posted @ 2011-07-03 22:22 [ 王志偉 ] 閱讀(784) | 評論 (0)編輯 收藏

          性能測試過程中,我們該如何監控java虛擬機內存的使用情況,用以判斷JVM是否存在內存問題呢?如何判斷JVM垃圾回收是否正常?一般的top指令基本上滿足不了這樣的需求,因為它主要監控的是總體的系統資源,很難定位到java應用程序。
          在項目實踐過程中,我們探索和使用了一款新工具--Jstat。
              先秀一下。Jstat是JDK自帶的一個輕量級小工具。全稱“Java Virtual Machine statistics monitoring tool”,它位于java的bin目錄下,主要利用JVM內建的指令對Java應用程序的資源和性能進行實時的命令行的監控,包括了對Heap size和垃圾回收狀況的監控??梢?,Jstat是輕量級的、專門針對JVM的工具,非常適用。
          那,該怎么用呢?
              語法結構如下:jstat [Options] vmid [interval] [count]
              Options — 選項,我們一般使用 -gcutil 查看gc情況
              vmid    — VM的進程號,即當前運行的java進程號
              interval– 間隔時間,單位為秒或者毫秒
              count   — 打印次數,如果缺省則打印無數次
              下面給出一個實際的例子:

           

                      

          注:由于JVM內存設置較大,圖中百分比變化不太明顯

           

              圖中參數含義如下:

              S0 — Heap上的 Survivor space 0 區已使用空間的百分比
              S1 — Heap上的 Survivor space 1 區已使用空間的百分比
              E   — Heap上的 Eden space 區已使用空間的百分比
              O   — Heap上的 Old space 區已使用空間的百分比
              P   — Perm space 區已使用空間的百分比
              YGC — 從應用程序啟動到采樣時發生 Young GC 的次數
              YGCT– 從應用程序啟動到采樣時 Young GC 所用的時間(單位秒)
              FGC — 從應用程序啟動到采樣時發生 Full GC 的次數
              FGCT– 從應用程序啟動到采樣時 Full GC 所用的時間(單位秒)
              GCT — 從應用程序啟動到采樣時用于垃圾回收的總時間(單位秒)

              上圖的示例,紅框中,我們可以看到,5次young gc之后,垃圾內存被從Eden space區(E)放入了Old space區(O),并引起了百分比的變化,導致Survivor space使用的百分比從19.69%(S0)降到10.34%(S1)。有效釋放了內存空間。綠框中,我們可以看到,一次full gc之后,Old space區(O)的內存被回收,從36.81%降到35.01%。

              圖中同時打印了young gc和full gc的總次數、總耗時。而,每次young gc消耗的時間,可以用相間隔的兩行YGCT相減得到。每次full gc消耗的時間,可以用相隔的兩行FGCT相減得到。例如紅框中表示的第一行、第二行之間發生了1次young gc,消耗的時間為52.281-52.252=0.029秒。

              常駐內存區(P)的使用率,始終停留在37.6%左右,說明常駐內存沒有突變,比較正常。

          如果young gc和full gc能夠正常發生,而且都能有效回收內存,常駐內存區變化不明顯,則說明java內存釋放情況正常,垃圾回收及時,java內存泄露的幾率就會大大降低。但也不能說明一定沒有內存泄露。

           

              以上,介紹了Jstat按百分比查看gc情況的功能。其實,它還有其它功能,例如加載類信息統計功能、內存池信息統計功能等,那些是以絕對值的形式打印出來的,比較少用,在此就不做介紹。

            

              為了更全面的監控JVM內存使用情況,我們需要引入更強大的工具來進一步分析–JConsole。敬請關注。

          --------

          一、概述

              SUN 的JDK中的幾個工具,非常好用。秉承著有免費,不用商用的原則。以下簡單介紹一下這幾種工具。(注:本文章下的所有工具都存在JDK5.0以上版本的工具集里,同javac一樣,不須特意安裝) 。
             
              我一共找到以下四個工具:重點看看jconsole和jmap。

          jps    
          :與unix上的ps類似,用來顯示本地的java進程,可以查看本地運行著幾個java程序,并顯示他們的進程號。    
             
          jstat    
          :一個極強的監視VM內存工具。可以用來監視VM內存內的各種堆和非堆的大小及其內存使用量。    
             
          jmap    
          :打印出某個java進程(使用pid)內存內的,所有‘對象’的情況(如:產生那些對象,及其數量)。    
             
          jconsole    
          :一個java GUI監視工具,可以以圖表化的形式顯示各種數據。并可通過遠程連接監視遠程的服務器VM。




           

          二、 使用介紹:
             
              1、jstat :我想很多人都是用過unix系統里的ps命令,這個命令主要是用來顯示當前系統的進程情況,有哪些進程,及其 id。 jps 也是一樣,它的作用是顯示當前系統的java進程情況,及其id號。我們可以通過它來查看我們到底啟動了幾個java進程(因為每一個java程序都會獨占一個java虛擬機實例),和他們的進程號(為下面幾個程序做準備),并可通過opt來查看這些進程的詳細啟動參數。
              使用方法:在當前命令行下打 jps(需要JAVA_HOME,沒有的話,到改程序的目錄下打) 。

          可惜沒有linux下的ps好用,名稱不好用。但是在第四個工具jconsole的界面里面會有具體JAR包的名稱。
             
              2、jstat :對VM內存使用量進行監控。
              jstat工具特別強大,有眾多的可選項,詳細查看堆內各個部分的使用量,以及加載類的數量。使用時,需加上查看進程的進程id,和所選參數。以下詳細介紹各個參數的意義。
              jstat -class pid:顯示加載class的數量,及所占空間等信息。
              jstat -compiler pid:顯示VM實時編譯的數量等信息。
              jstat -gc pid:可以顯示gc的信息,查看gc的次數,及時間。其中最后五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。
              jstat -gccapacity:可以顯示,VM內存中三代(young,old,perm)對象的使用和占用大小,如:PGCMN顯示的是最小perm的內存使用量,PGCMX顯示的是perm的內存最大使用量,PGC是當前新生成的perm內存占用量,PC是但前perm內存占用量。其他的可以根據這個類推, OC是old內純的占用量。
              jstat -gcnew pid:new對象的信息。
              jstat -gcnewcapacity pid:new對象的信息及其占用量。
              jstat -gcold pid:old對象的信息。
              jstat -gcoldcapacity pid:old對象的信息及其占用量。
              jstat -gcpermcapacity pid: perm對象的信息及其占用量。
              jstat -util pid:統計gc信息統計。
              jstat -printcompilation pid:當前VM執行的信息。
              除了以上一個參數外,還可以同時加上 兩個數字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,還可以加上-h3每三行顯示一下標題。
             
             3、jmap 是一個可以輸出所有內存中對象的工具,甚至可以將VM 中的heap,以二進制輸出成文本。使用方法 jmap -histo pid。如果連用 SHELL jmap -histo pid>a.log可以將其保存到文本中去(windows下也可以使用),在一段時間后,使用文本對比工具,可以對比出GC回收了哪些對象。jmap -dump:format=b,file=f1 3024可以將3024進程的內存heap輸出出來到f1文件里。
             
              4、jconsole 是一個用java寫的GUI程序,用來監控VM,并可監控遠程的VM,非常易用,而且功能非常強。由于是GUI程序,這里就不詳細介紹了,不會的地方可以參考SUN的官方文檔。
              使用方法:命令行里打 jconsole,選則進程就可以了。
             
              友好提示:windows查看進程號,由于任務管理器默認的情況下是不顯示進程id號的,所以可以通過如下方法加上。ctrl+alt+del打開任務管理器,選擇‘進程’選項卡,點‘查看’->''選擇列''->加上''PID'',就可以了。當然還有其他很好的選項。

           

          三、參考資料:

              article:http://elf8848.javaeye.com/blog/442806


              jps:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html


              jstat:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html


              jmap:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jmap.html


              jconsole:http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html    

          posted @ 2011-05-29 23:08 [ 王志偉 ] 閱讀(7500) | 評論 (0)編輯 收藏
          PermGen space這一部分用于存放Class和Meta的信息,Class在被 Load的時候被放入PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。
          我在做TMS的發布工具的時候,就遇到了問題,這個工具的目的是把一個相同的系統,在tomcat下自動的發布多份,但當卸載,重新發布多次后, tomcat就掛了,整個電腦如同死機一般。后來使用文章里的set JAVA_OPTS=-server -Xms800m -Xmx800m -XX:PermSize=64M-XX:MaxNewSize=256m-XX:MaxPermSize=128m -Djava.awt.headless=true 解決了問題,不過在2G的電腦上,我是把-XX:MaxPermSize=128m 調到了-XX:MaxPermSize=256m。另外我還嘗試了把所有的lib都放到tomcat的lib下,一些lib就不能在本項目中再出現了。
          現在看,還是spring,hibernate之類的產生的類導致PermGen space空間不足造成的這些問題。
          http://www.javaeye.com/topic/80620?page=1 這個帖子里討論了這個問題,有人做了些有益的分析可以看看。
          我又繼續在我的筆記本上做了測試T42,1G內存。tomcat版本6.0.14。
          set JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless=true
          這個配置反復發布是可以的,另外又一次測試了將項目下的jar包放到tomcat的lib下的對比。重新安裝一個lib下為空的程序是10秒,否則是30秒。

          總結一下:
          1、修改tomcat的啟動參數,類似如下的樣子
          set JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
           
          echo Using CATALINA_BASE:   %CATALINA_BASE%
          echo Using CATALINA_HOME:   %CATALINA_HOME%
          echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR%
          if ""%1"" == ""debug"" goto use_jdk
          echo Using JRE_HOME:        %JRE_HOME%
          goto java_dir_displayed
          :use_jdk
          echo Using JAVA_HOME:       %JAVA_HOME%
          :java_dir_displayed

          echo Using JAVA_OPTS: %JAVA_OPTS%
          set JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

          2、將通用的lib文件放到tomcat的目錄下
          posted @ 2011-05-29 23:05 [ 王志偉 ] 閱讀(365) | 評論 (0)編輯 收藏

           POJO(Plain Old Java Object)這種叫法是Martin Fowler、Rebecca Parsons和Josh MacKenzie在2000年的一次演講的時候提出來的。
                我在做J2EE培訓中發現我的很多學生問我什么是POJO,后來我在寫書(《Spring2初學者實踐教材》和《Spring3初學者實踐教材》)的時候發現POJO這個概念無法回避?,F在網上對于POJO的解釋很多,但是很多都是有錯誤的或者不夠準確。對此我一開始也是存在誤區的,我原來是這樣理解的:
                  POJO是這樣的一種“純粹的”JavaBean,在它里面除了JavaBean規范的方法和屬性沒有別的東西,即private屬性以及對這個屬性方法的public的get和set方法。我們會發現這樣的JavaBean很“單純”,它只能裝載數據,作為數據存儲的載體,而不具有業務邏輯處理的能力。
              所以下面的代碼被認為是POJO了。

          package com.tongking.spring;


          public class DbHello implements Hello {

                 private DictionaryDAO dao;

                 public void setDao(DictionaryDAO dao) {

                        this.dao = dao;

                 }

          }

                  其實,這樣的認為是錯誤的,我仔細閱讀了《POJOs in Action》這本書的有關部分和POJO的最原始的出處http://martinfowler.com/bliki/POJO.html,
                  The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk we were pointing out the many benefits of encoding business logic into regular java objects rather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it''s caught on very nicely.
          基本的意思是我們要給具有業務邏輯處理的規則的Java對象(regular java objects)起了一個名字——POJO,這些Java對象不是EntityBeans(EJB的一種)。


                  我又在http://www.webopedia.com/TERM/P/POJO.htm查到解釋如下:

          POJO, or Plain Old Java Object, is a normal Java object class (that is, not a JavaBean, EntityBean etc.)  and does not serve any other special role nor does it implement any special interfaces of any of the Java frameworks. This term was coined by Martin Fowler, Rebbecca Parsons and Josh MacKenzie who believed that by creating the acronym POJO, such objects would have a "fancy name", thereby convincing people that they were worthy of use.
                  基本意思是說POJO一個正規的Java對象(不是JavaBean,EntityBean等),也不擔當任何的特殊的角色,也不實現任何Java框架指定的接口。
                  我覺得上面的解釋很準確,POJO應該不是我們開始認為的JavaBean,當然更不是EJB,它不應該依賴于框架即繼承或實現某些框架類或接口。例如:Struts1中的Action和ActionForm當然不屬于POJO了,而在Struts2中的Action由于可以不繼承任何的接口,所以在這種情況下Action是POJO,但是Struts2中的Action也可以繼承ActionSupport類就不再屬于POJO了。POJO里面是可以包含業務邏輯處理和持久化邏輯,也可以包含類似與JavaBean屬性和對屬性訪問的set和get方法的。
                 最后,我們總結一下給一個定義把,POJO是一個簡單的、正規Java對象,它包含業務邏輯處理或持久化邏輯等,但不是JavaBean、EntityBean等,不具有任何特殊角色和不繼承或不實現任何其它Java框架的類或接口。

          文章出處:飛諾網(www.firnow.com):http://dev.firnow.com/course/3_program/java/javashl/200845/108451.html

          posted @ 2011-04-19 11:00 [ 王志偉 ] 閱讀(356) | 評論 (0)編輯 收藏

          非侵入式系介紹DI用語,我得理解是兩個組件(類,接口)之間,比較獨立,不深入到另一個類內部,哪位大蝦能點撥一二?

           

          關于“侵入式”和“非侵入式”設計

          有讀者講“侵入式”這一術語無法理解,這里給一個簡單解釋,是我個人的看法。

          在設計一個類時,按理說,需要考慮的應該只是該類所企圖表示的那個“概念”本身:為表示有關概念應記錄哪些信息,該類的對象與外界交換信息的界面等等。但定義這個類并不是為了放在那里觀賞,而是為了使用。在考慮類對象的使用時,使用環境的一些要素就可能“侵入”這個類的設計之中。實際上,許多情況下我們常??梢栽?#8220;侵入式”設計和“非侵入式”設計之間做一個選擇,不同選擇各有優缺點。在考慮非類的程序部分時,這種問題也同樣存在。

          例如,我們可能需要對類A的對象做引用計數,這里有兩種基本可能性:將計數功能納入類A的設計內(侵入式引用計數設計,此時類A的對象中包含了與引用計數有關的要素,這顯然是與類A所要表示的概念無關的東西),或者將計數功能放在類A之外(非侵入式引用計數)。

          本書中討論容器時提出了“侵入式容器”設計和“非侵入式容器”設計的概念:當我們希望將類A的對象放入一種容器時,是否需要將該容器的實現要素“侵入”類A的設計實現之中(這顯然是與類A本身并無必然關系的要素)。不同考慮導致不同的容器設計。  

           

          我基本上知道了,從夏大蝦得著作中得知。
          比如struts,需要繼承一些struts得類,這就是侵入式,使得系統離不開那個框架。
          而spring中,業務類不需要繼承框架得類,將來拋棄spring也比較方便。
          樓上大蝦(土豆塊)能否談下ejb與spring之間得關系。你用ejb嗎?如果用了,感覺如何?

           

          非侵入式(non-intrusive)設計是目前非常熱門的話題。在一般的討論中,非侵入式設計總是和Spring這樣的IoC容器或者AOP技術聯系在一起。但是從思想上說,non-intrusive并不等價于IoC或者AOP,它是一個比AOP更加寬泛的概念。
                首先,我們考察一下何謂intrusive。典型的intrusive實現是繼承特定的基類, 或者實現特定的接口. 在抽象的意義上說, intrusive意味著在基礎結構中預留了一些特殊的,專用的結構, 這些結構對于基礎功能而言不僅僅是無用的, 甚至是有害的, 例如影響性能或者模糊了原有的概念結構, 而系統整體的后期擴展能力也受到這些預設的結構通道的限制.
          non-intrusive設計的基本特點是盡量利用基礎結構的元素, 而不是引入額外的特殊結構.例如, 在witrix平臺的tpl模板中
          <button tpl:tag="ui:FlatButton" value="xx" onclick="alert('ok')" />
          如果后臺tpl引擎不解析<ui:FlatButton>標簽, 那么該標簽的表現就是普通的html button. 這里整個頁面的界面表現結構沒有被tpl標簽所破壞,而如果像jsp tag那樣強行規定必須采用節點語法, 即
          <ui:FlatButton value="xx" onclick="alert('ok')" />
          則在沒有tpl引擎的情況下, 界面結構被tpl標簽所破壞,此時在dreamweaver這樣的可視化工具中我們無法再識別出有效的界面元素, 喪失了WYSIWYG編輯的能力.
          tpl:tag屬性屬于html語法本身規定了的自定義屬性, 它在html中的存在是符合規范的, 而且它對于button來說沒有造成什么限制或損害, 因而是一種無害的標記. 在沒有tpl模板引擎的情況下, tpl:tag屬性與其他自定義屬性一樣處于同樣的地位, 沒有什么特殊的作用. 而一旦tpl模板引擎識別出該特殊標記, 整個節點就被解釋成一個具有豐富表現形式的平面按鈕而不是系統缺省風格的普通按鈕. 從級列設計的角度上說, button對應于ui:FlatButton在沒有tpl解析能力情況時退化了的結果. 在EJB3的規范中, 普通的POJO(Plain Old Java Object)對象在經過無害的標記(annotation)之后通過Enhance過程獲得持久化等特性, POJO正對應于EJB Object的退化形式. 在某種意義上我們可以說, 存在著多少種可退化方式,就對應著多少種non-intrusive design。
                與傳統設計中的結構堆砌不同, 現代技術更加強調在原有結構基礎上的同態變化, 關注原有結構中的某些部分出現特殊意義后所產生的對稱破缺. 在non-intrusive設計中, 基礎的結構中沒有為擴展內置什么特殊的結構, 一般僅僅是標記而已, 這些標記是無害的甚至本身在基礎結構中是有用的, 例如某些javascript庫在前臺html頁面中利用html標簽的class屬性作為標記. 為了識別這些屬于結構標準部分的標記并對之進行處理,我們需要一種可選擇的結構透明性, 具體來說我們需要能滲透到系統內部,準確的定位到標記處. 這就類似于x光檢測, x光只與某些特殊材料發生強烈作用而普通部分對于x光而言是透明的. 而當外部引擎識別出這些特殊的標記之后, 可能需要操縱該局部結構, 例如在基礎結構中插入一些新的結構以實現基礎結構的增強. 這些都可能需要應用類似于AOP的技術, 而在這一增強過程中關于擴展結構的具體知識存在于擴展引擎中而不是基礎結構中, 因而往往整體表現出一種IoC的特性.


          轉自:http://hi.baidu.com/westsky/blog/item/46d452f0127cebaaa50f522f.html
          posted @ 2011-04-19 10:23 [ 王志偉 ] 閱讀(4589) | 評論 (0)編輯 收藏

          <1> js或者jQuery訪問頁面中的框架iframe.
          注意:框架內的頁面是不能跨域的! 假設有兩個頁面,在相同域下.

           

          假設:父窗口  index.html ,有 id 為 subifrm 的 iframe

           

          1. 在index.html執行JS直接訪問子窗口中某元素 :

          document.getElementById('subifrm').contentWindow.document.getElementById('test').style.color='red'  

          2. 利用jquery 來訪問子窗口

          $("#subifrm").contents().find("#test").css('color','red');

          ====================================================================

          ====================================================================

           

          <2> 用DOM方法與jquery方法結合的方式實現互動操作

          1.在父窗口中操作 選中IFRAME中的所有單選鈕

          $(window.frames["iframe1"].document).find("input[@type='radio']").attr("checked","true"); 

          2.在IFRAME中操作 選中父窗口中的所有單選鈕
          $(window.parent.document).find("input[@type='radio']").attr("checked","true"); 

          ====================================================================

          ====================================================================

           

          <3> 使用jquery操作iframe

          1 頁面里有兩個ifame

          <iframe id="leftiframe"></iframe>     
          <iframe id="mainiframe></iframe>    
          <iframe id="leftiframe"></iframe>  
          <iframe id="mainiframe></iframe> 

          leftiframe中jQuery改變mainiframe的src代碼:

          $("#mainframe",parent.document.body).attr("src","http://www.baidu.com"

          2、 如果內容里面有一個ID為mainiframe的ifame

          <iframe id="mainifame"></ifame>     
          <iframe id="mainifame"></ifame> 

          ifame包含一個someID

          <div id="someID">you want to get this content</div>     
          <div id="someID">you want to get this content</div>

          得到someID的內容

          $("#mainiframe").contents().find("someID").html();或者$("#mainiframe").contains().find("someID").text();   
          $(
          "#mainiframe").contents().find("someID").html();或者$("#mainiframe").contains().find("someID").text(); 

          $(
          "#mainiframe").contents().find("someID").html();或者$("#mainiframe").contains().find("someID").text(); 


          2 、如上面所示
             leftiframe中的jQuery操作mainiframe的內容someID的內容

          $("#mainframe",parent.document.body).contents().find("someID").html();或者 $("#mainframe",parent.document.body).contents().find("someID").val();

          source:http://suan2046.javaeye.com/blog/575421
          posted @ 2011-03-07 14:14 [ 王志偉 ] 閱讀(895) | 評論 (0)編輯 收藏
          僅列出標題  

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(1)

          隨筆檔案(3)

          文章檔案(29)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 荣昌县| 夏邑县| 塔城市| 稻城县| 五莲县| 西充县| 秦皇岛市| 汕头市| 辽中县| 循化| 古交市| 定州市| 花垣县| 阳东县| 景洪市| 韶山市| 鄄城县| 运城市| 宣汉县| 东海县| 喀喇| 宁夏| 湘乡市| 故城县| 贵州省| 游戏| 巴塘县| 耿马| 沂源县| 砚山县| 右玉县| 玉环县| 扎赉特旗| 岑巩县| 略阳县| 清原| 黑山县| 来安县| 临泽县| 商南县| 宁夏|