當前位置:首頁 » 編程語言 » 減少sql資料庫訪問措施
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

減少sql資料庫訪問措施

發布時間: 2022-06-21 16:38:19

⑴ 50、怎麼減少請求對資料庫的直接訪問

1、先創建程序所要訪問的資料庫,打開控制面板,建立ODBC數據源:開始→設置→控制面板→管理工具→ODBC數據源→系統DSN。
2、然後編寫資料庫訪問程序:在程序中首先要載入驅動,其次要建立連接,再次創建用於訪問資料庫的Statement對象,然後利用Statement對象訪問資料庫
Class.forName(「sun.jdbc.odbc.JdbcOdbcDriver」);
String url="jdbc:odbc:book";
String query="SELECT * FROM book1";
Connection c =DriverManager.getConnection( Url,user,password);
Connection con=DriverManager.getConnection(url);
Statement stmt =con.createStatement( );
ResultSet rs=stmt1.executeQuery(query);
建立連接之後,可以訪問資料庫,對資料庫進行操作,如:查詢、修改、刪除。
連接使用完畢,可以調用close ( )方法關閉連接.

import java.sql.*;
class SimpleSelect{
public static void main(String args[]){
String url="jdbc:odbc:book";
String query="SELECT * FROM book1";
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(java.lang.ClassNotFoundException e){
System.err.print("ERROR:");
System.err.print(e.getMessage());
}
//輸出資料庫中信息
try{
Connection con=DriverManager.getConnection(url);
Statement stmt=con.createStatement();
ResultSet r=stmt.executeQuery(query);
System.out.println("id:"+" "+"name"+" "+"price"+" "+"author"+" "+"publish_name");

while(r.next()){
Long r1=r.getLong("id");

⑵ 減輕 訪問SQL Server資料庫的負擔,該怎麼做

資料庫優化設計方案
本文首先討論了基於第三範式的資料庫表的基本設計,著重論述了建立主鍵和索引的策略和方案,然後從資料庫表的擴展設計和庫表對象的放置等角度概述了資料庫管理系統的優化方案。

1 引言
資料庫優化的目標無非是避免磁碟I/O瓶頸、減少CPU利用率和減少資源競爭。為了便於讀者閱讀和理解,筆者參閱了Sybase、Informix和 Oracle等大型資料庫系統參考資料,基於多年的工程實踐經驗,從基本表設計、擴展設計和資料庫表對象放置等角度進行討論,著重討論了如何避免磁碟 I/O瓶頸和減少資源競爭,相信讀者會一目瞭然。

2 基於第三範式的基本表設計

在基於表驅動的信息管理系統(MIS)中,基本表的設計規范是第三範式(3NF)。第三範式的基本特徵是非主鍵屬性只依賴於主鍵屬性。基於第三範式的資料庫表設計具有很多優點:一是消除了冗餘數據,節省了磁碟存儲空間;二是有良好的數據完整性限制,即基於主外鍵的參照完整限制和基於主鍵的實體完整性限制,這使得數據容易維護,也容易移植和更新;三是數據的可逆性好,在做連接(Join)查詢或者合並表時不遺漏、也不重復;四是因消除了冗餘數據(冗餘列),在查詢(Select)時每個數據頁存的數據行就多,這樣就有效地減少了邏輯I/O,每個Cash存的頁面就多,也減少物理I/O;五是對大多數事務 (Transaction)而言,運行性能好;六是物理設計(Physical Design)的機動性較大,能滿足日益增長的用戶需求。

在基本表設計中,表的主鍵、外鍵、索引設計佔有非常重要的地位,但系統設計人員往往只注重於滿足用戶要求,而沒有從系統優化的高度來認識和重視它們。實際上,它們與系統的運行性能密切相關。現在從系統資料庫優化角度討論這些基本概念及其重要意義:

(1)主鍵(Primary Key):主鍵被用於復雜的SQL語句時,頻繁地在數據訪問中被用到。一個表只有一個主鍵。主鍵應該有固定值(不能為Null或預設值,要有相對穩定性),不含代碼信息,易訪問。把常用(眾所周知)的列作為主鍵才有意義。短主鍵最佳(小於25bytes),主鍵的長短影響索引的大小,索引的大小影響索引頁的大小,從而影響磁碟I/O。主鍵分為自然主鍵和人為主鍵。自然主鍵由實體的屬性構成,自然主鍵可以是復合性的,在形成復合主鍵時,主鍵列不能太多,復合主鍵使得Join*作復雜化、也增加了外鍵表的大小。人為主鍵是,在沒有合適的自然屬性鍵、或自然屬性復雜或靈敏度高時,人為形成的。人為主鍵一般是整型值(滿足最小化要求),沒有實際意義,也略微增加了表的大小;但減少了把它作為外鍵的表的大小。

(2)外鍵(Foreign Key):外鍵的作用是建立關系型資料庫中表之間的關系(參照完整性),主鍵只能從獨立的實體遷移到非獨立的實體,成為後者的一個屬性,被稱為外鍵。

(3)索引(Index):利用索引優化系統性能是顯而易見的,對所有常用於查詢中的Where子句的列和所有用於排序的列創建索引,可以避免整表掃描或訪問,在不改變表的物理結構的情況下,直接訪問特定的數據列,這樣減少數據存取時間;利用索引可以優化或排除耗時的分類*作;把數據分散到不同的頁面上,就分散了插入的數據;主鍵自動建立了唯一索引,因此唯一索引也能確保數據的唯一性(即實體完整性);索引碼越小,定位就越直接;新建的索引效能最好,因此定期更新索引非常必要。索引也有代價:有空間開銷,建立它也要花費時間,在進行Insert、Delete和Update*作時,也有維護代價。索引有兩種:聚族索引和非聚族索引。一個表只能有一個聚族索引,可有多個非聚族索引。使用聚族索引查詢數據要比使用非聚族索引快。在建索引前,應利用資料庫系統函數估算索引的大小。

① 聚族索引(Clustered Index):聚族索引的數據頁按物理有序儲存,佔用空間小。選擇策略是,被用於Where子句的列:包括范圍查詢、模糊查詢或高度重復的列(連續磁碟掃描);被用於連接Join*作的列;被用於Order by和Group by子句的列。聚族索引不利於插入*作,另外沒有必要用主鍵建聚族索引。

② 非聚族索引(Nonclustered Index):與聚族索引相比,佔用空間大,而且效率低。選擇策略是,被用於Where子句的列:包括范圍查詢、模糊查詢(在沒有聚族索引時)、主鍵或外鍵列、點(指針類)或小范圍(返回的結果域小於整表數據的20%)查詢;被用於連接Join*作的列、主鍵列(范圍查詢);被用於Order by和Group by子句的列;需要被覆蓋的列。對只讀表建多個非聚族索引有利。索引也有其弊端,一是創建索引要耗費時間,二是索引要佔有大量磁碟空間,三是增加了維護代價(在修改帶索引的數據列時索引會減緩修改速度)。那麼,在哪種情況下不建索引呢?對於小表(數據小於5頁)、小到中表(不直接訪問單行數據或結果集不用排序)、單值域(返回值密集)、索引列值太長(大於20bitys)、容易變化的列、高度重復的列、Null值列,對沒有被用於Where子語句和 Join查詢的列都不能建索引。另外,對主要用於數據錄入的,盡可能少建索引。當然,也要防止建立無效索引,當Where語句中多於5個條件時,維護索引的開銷大於索引的效益,這時,建立臨時表存儲有關數據更有效。

批量導入數據時的注意事項:在實際應用中,大批量的計算(如電信話單計費)用C語言程序做,這種基於主外鍵關系數據計算而得的批量數據(文本文件),可利用系統的自身功能函數(如Sybase的BCP命令)快速批量導入,在導入資料庫表時,可先刪除相應庫表的索引,這有利於加快導入速度,減少導入時間。在導入後再重建索引以便優化查詢。

(4)鎖:鎖是並行處理的重要機制,能保持數據並發的一致性,即按事務進行處理;系統利用鎖,保證數據完整性。因此,我們避免不了死鎖,但在設計時可以充分考慮如何避免長事務,減少排它鎖時間,減少在事務中與用戶的交互,杜絕讓用戶控制事務的長短;要避免批量數據同時執行,尤其是耗時並用到相同的數據表。鎖的徵用:一個表同時只能有一個排它鎖,一個用戶用時,其它用戶在等待。若用戶數增加,則Server的性能下降,出現「假死」現象。如何避免死鎖呢?從頁級鎖到行級鎖,減少了鎖徵用;給小表增加無效記錄,從頁級鎖到行級鎖沒有影響,若在同一頁內競爭有影響,可選擇合適的聚族索引把數據分配到不同的頁面;創建冗餘表;保持事務簡短;同一批處理應該沒有網路交互。

(5)查詢優化規則:在訪問資料庫表的數據(Access Data)時,要盡可能避免排序(Sort)、連接(Join)和相關子查詢*作。經驗告訴我們,在優化查詢時,必須做到:
① 盡可能少的行;
② 避免排序或為盡可能少的行排序,若要做大量數據排序,最好將相關數據放在臨時表中*作;用簡單的鍵(列)排序,如整型或短字元串排序;
③ 避免表內的相關子查詢;
④ 避免在Where子句中使用復雜的表達式或非起始的子字元串、用長字元串連接;
⑤ 在Where子句中多使用「與」(And)連接,少使用「或」(Or)連接;
⑥ 利用臨時資料庫。在查詢多表、有多個連接、查詢復雜、數據要過濾時,可以建臨時表(索引)以減少I/O。但缺點是增加了空間開銷。
除非每個列都有索引支持,否則在有連接的查詢時分別找出兩個動態索引,放在工作表中重新排序。

3 基本表擴展設計
基於第三範式設計的庫表雖然有其優越性(見本文第一部分),然而在實際應用中有時不利於系統運行性能的優化:如需要部分數據時而要掃描整表,許多過程同時競爭同一數據,反復用相同行計算相同的結果,過程從多表獲取數據時引發大量的連接*作,當數據來源於多表時的連接*作;這都消耗了磁碟I/O和CPU時間。

尤其在遇到下列情形時,我們要對基本表進行擴展設計:許多過程要頻繁訪問一個表、子集數據訪問、重復計算和冗餘數據,有時用戶要求一些過程優先或低的響應時間。

如何避免這些不利因素呢?根據訪問的頻繁程度對相關表進行分割處理、存儲冗餘數據、存儲衍生列、合並相關表處理,這些都是克服這些不利因素和優化系統運行的有效途徑。

3.1 分割表或儲存冗餘數據
分割表分為水平分割表和垂直分割表兩種。分割表增加了維護數據完整性的代價。
水平分割表:一種是當多個過程頻繁訪問數據表的不同行時,水平分割表,並消除新表中的冗餘數據列;若個別過程要訪問整個數據,則要用連接*作,這也無妨分割表;典型案例是電信話單按月分割存放。另一種是當主要過程要重復訪問部分行時,最好將被重復訪問的這些行單獨形成子集表(冗餘儲存),這在不考慮磁碟空間開銷時顯得十分重要;但在分割表以後,增加了維護難度,要用觸發器立即更新、或存儲過程或應用代碼批量更新,這也會增加額外的磁碟I/O開銷。

垂直分割表(不破壞第三範式),一種是當多個過程頻繁訪問表的不同列時,可將表垂直分成幾個表,減少磁碟I/O(每行的數據列少,每頁存的數據行就多,相應佔用的頁就少),更新時不必考慮鎖,沒有冗餘數據。缺點是要在插入或刪除數據時要考慮數據的完整性,用存儲過程維護。另一種是當主要過程反復訪問部分列時,最好將這部分被頻繁訪問的列數據單獨存為一個子集表(冗餘儲存),這在不考慮磁碟空間開銷時顯得十分重要;但這增加了重疊列的維護難度,要用觸發器立即更新、或存儲過程或應用代碼批量更新,這也會增加額外的磁碟I/O開銷。垂直分割表可以達到最大化利用Cache的目的。

總之,為主要過程分割表的方法適用於:各個過程需要表的不聯結的子集,各個過程需要表的子集,訪問頻率高的主要過程不需要整表。在主要的、頻繁訪問的主表需要表的子集而其它主要頻繁訪問的過程需要整表時則產生冗餘子集表。
注意,在分割表以後,要考慮重新建立索引。

3.2 存儲衍生數據
對一些要做大量重復性計算的過程而言,若重復計算過程得到的結果相同(源列數據穩定,因此計算結果也不變),或計算牽扯多行數據需額外的磁碟I/O開銷,或計算復雜需要大量的CPU時間,就考慮存儲計算結果(冗餘儲存)。現予以分類說明:
若在一行內重復計算,就在表內增加列存儲結果。但若參與計算的列被更新時,必須要用觸發器更新這個新列。

若對表按類進行重復計算,就增加新表(一般而言,存放類和結果兩列就可以了)存儲相關結果。但若參與計算的列被更新時,就必須要用觸發器立即更新、或存儲過程或應用代碼批量更新這個新表。

若對多行進行重復性計算(如排名次),就在表內增加列存儲結果。但若參與計算的列被更新時,必須要用觸發器或存儲過程更新這個新列。

總之,存儲冗餘數據有利於加快訪問速度;但違反了第三範式,這會增加維護數據完整性的代價,必須用觸發器立即更新、或存儲過程或應用代碼批量更新,以維護數據的完整性。

3.3 消除昂貴結合
對於頻繁同時訪問多表的一些主要過程,考慮在主表內存儲冗餘數據,即存儲冗餘列或衍生列(它不依賴於主鍵),但破壞了第三範式,也增加了維護難度。在源表的相關列發生變化時,必須要用觸發器或存儲過程更新這個冗餘列。當主要過程總同時訪問兩個表時可以合並表,這樣可以減少磁碟I/O*作,但破壞了第三範式,也增加了維護難度。對父子表和1:1關系表合並方法不同:合並父子表後,產生冗餘表;合並1:1關系表後,在表內產生冗餘數據。

4 資料庫對象的放置策略
資料庫對象的放置策略是均勻地把數據分布在系統的磁碟中,平衡I/O訪問,避免I/O瓶頸。

⑴ 訪問分散到不同的磁碟,即使用戶數據盡可能跨越多個設備,多個I/O運轉,避免I/O競爭,克服訪問瓶頸;分別放置隨機訪問和連續訪問數據。
⑵ 分離系統資料庫I/O和應用資料庫I/O。把系統審計表和臨時庫表放在不忙的磁碟上。
⑶ 把事務日誌放在單獨的磁碟上,減少磁碟I/O開銷,這還有利於在障礙後恢復,提高了系統的安全性。
⑷ 把頻繁訪問的「活性」表放在不同的磁碟上;把頻繁用的表、頻繁做Join*作的表分別放在單獨的磁碟上,甚至把把頻繁訪問的表的欄位放在不同的磁碟上,把訪問分散到不同的磁碟上,避免I/O爭奪;
⑸ 利用段分離頻繁訪問的表及其索引(非聚族的)、分離文本和圖像數據。段的目的是平衡I/O,避免瓶頸,增加吞吐量,實現並行掃描,提高並發度,最大化磁碟的吞吐量。利用邏輯段功能,分別放置「活性」表及其非聚族索引以平衡I/O。當然最好利用系統的默認段。另外,利用段可以使備份和恢復數據更加靈活,使系統授權更加靈活。

⑶ 資料庫性能優化有哪些措施

1、調整數據結構的設計。這一部分在開發信息系統之前完成,程序員需要考慮是否使用ORACLE資料庫的分區功能,對於經常訪問的資料庫表是否需要建立索引等。

2、調整應用程序結構設計。這一部分也是在開發信息系統之前完成,程序員在這一步需要考慮應用程序使用什麼樣的體系結構,是使用傳統的Client/Server兩層體系結構,還是使用Browser/Web/Database的三層體系結構。不同的應用程序體系結構要求的資料庫資源是不同的。

3、調整資料庫SQL語句。應用程序的執行最終將歸結為資料庫中的SQL語句執行,因此SQL語句的執行效率最終決定了ORACLE資料庫的性能。ORACLE公司推薦使用ORACLE語句優化器(Oracle Optimizer)和行鎖管理器(row-level manager)來調整優化SQL語句。

4、調整伺服器內存分配。內存分配是在信息系統運行過程中優化配置的,資料庫管理員可以根據資料庫運行狀況調整資料庫系統全局區(SGA區)的數據緩沖區、日誌緩沖區和共享池的大小;還可以調整程序全局區(PGA區)的大小。需要注意的是,SGA區不是越大越好,SGA區過大會佔用操作系統使用的內存而引起虛擬內存的頁面交換,這樣反而會降低系統。

5、調整硬碟I/O,這一步是在信息系統開發之前完成的。資料庫管理員可以將組成同一個表空間的數據文件放在不同的硬碟上,做到硬碟之間I/O負載均衡。

6、調整操作系統參數,例如:運行在UNIX操作系統上的ORACLE資料庫,可以調整UNIX數據緩沖池的大小,每個進程所能使用的內存大小等參數。

資料庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,它產生於距今六十多年前,隨著信息技術和市場的發展,特別是二十世紀九十年代以後,數據管理不再僅僅是存儲和管理數據,而轉變成用戶所需要的各種數據管理的方式。資料庫有很多種類型,從最簡單的存儲有各種數據的表格到能夠進行海量數據存儲的大型資料庫系統都在各個方面得到了廣泛的應用。

在信息化社會,充分有效地管理和利用各類信息資源,是進行科學研究和決策管理的前提條件。資料庫技術是管理信息系統、辦公自動化系統、決策支持系統等各類信息系統的核心部分,是進行科學研究和決策管理的重要技術手段。

在經濟管理的日常工作中,常常需要把某些相關的數據放進這樣的「倉庫」,並根據管理的需要進行相應的處理。

例如,企業或事業單位的人事部門常常要把本單位職工的基本情況(職工號、姓名、年齡、性別、籍貫、工資、簡歷等)存放在表中,這張表就可以看成是一個資料庫。有了這個"數據倉庫"我們就可以根據需要隨時查詢某職工的基本情況,也可以查詢工資在某個范圍內的職工人數等等。這些工作如果都能在計算機上自動進行,那我們的人事管理就可以達到極高的水平。此外,在財務管理、倉庫管理、生產管理中也需要建立眾多的這種"資料庫",使其可以利用計算機實現財務、倉庫、生產的自動化管理。

(3)減少sql資料庫訪問措施擴展閱讀

資料庫,簡單來說是本身可視為電子化的文件櫃--存儲電子文件的處所,用戶可以對文件中的數據進行新增、截取、更新、刪除等操作。

資料庫指的是以一定方式儲存在一起、能為多個用戶共享、具有盡可能小的冗餘度的特點、是與應用程序彼此獨立的數據集合。

在經濟管理的日常工作中,常常需要把某些相關的數據放進這樣的"倉庫",並根據管理的需要進行相應的處理。

例如,企業或事業單位的人事部門常常要把本單位職工的基本情況(職工號、姓名、年齡、性別、籍貫、工資、簡歷等)存放在表中,這張表就可以看成是一個資料庫。有了這個"數據倉庫"我們就可以根據需要隨時查詢某職工的基本情況,也可以查詢工資在某個范圍內的職工人數等等。這些工作如果都能在計算機上自動進行,那我們的人事管理就可以達到極高的水平。此外,在財務管理、倉庫管理、生產管理中也需要建立眾多的這種"資料庫",使其可以利用計算機實現財務、倉庫、生產的自動化管理。

⑷ 怎麼減少sql的活動連接數

SQL的連接數無非就是訪問資料庫的次數,即請求的次數,而SQL連接數的減少或者是優化,主要是從你的代碼的邏輯上來做處理的,就像一個流水線的工作一樣,到最後一步才返回結果,程序中有很多的人喜歡將一個值取出來之後,然後再將這個值作為條件去查資料庫,這個完全沒有必要,直接在資料庫中將改值作為條件再判斷,然後將結果返回到頁面上即可,這樣連接數就達到了減少了

⑸ 如何減少對資料庫的訪問次數來加快sql執行

當執行每條SQL語句時, ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變數 , 讀數據塊等等. 由此可見,
減少訪問資料庫的次數 , 就能實際上減少ORACLE的工作量.

例如,

以下有三種方法可以檢索出雇員號等於0342或0291的職員.

方法1 (最低效)

SELECT
EMP_NAME , SALARY , GRADE

FROM EMP

WHERE EMP_NO = 342;

SELECT EMP_NAME , SALARY , GRADE

FROM EMP

WHERE
EMP_NO = 291;

方法2 (次低效)

DECLARE

CURSOR C1 (E_NO
NUMBER) IS

SELECT EMP_NAME,SALARY,GRADE

FROM EMP

WHERE
EMP_NO = E_NO;

BEGIN

OPEN C1(342);

FETCH C1 INTO …,..,..
;

…..

OPEN C1(291);

FETCH C1 INTO …,..,.. ;

CLOSE C1;

END;

方法3 (高效)

SELECT A.EMP_NAME ,
A.SALARY , A.GRADE,

B.EMP_NAME , B.SALARY , B.GRADE

FROM EMP
A,EMP B

WHERE A.EMP_NO = 342

AND B.EMP_NO = 291;

⑹ 可以通過減少表訪問次數來進一步優化該sql嗎

好像減少訪問次數不可能優化SQL資料庫,你可以這樣想,是否不訪問SQL資料庫就是最優的了?一般優化資料庫是清除資料庫中不必要的用戶數據表、表中欄位、表中記錄,在應用程序中優化訪問資料庫的代碼,才能達到優化資料庫的目的。

⑺ MSSQL資料庫如何優化

1. 保證在實現功能的基礎上,盡量減少對資料庫的訪問次數;通過搜索參數,盡量減少對表的訪問行數,最小化結果集,從而減輕網路負擔;能夠分開的操作盡量分開處理,提高每次的響應速度;、使用SQL時,盡量把使用的索引放在選擇的首列;演算法的結構盡量簡單;在查詢時,不要過多地使用通配符,而且要用到幾列就選擇幾列,如:
SELECT C1,C2 FROM T1;
在可能的情況下盡量限制盡量結果集行數,如:
SELECT TOP 300 C1,C2FROM T1,因為某些情況下用戶是不需要那麼多的數據的, 避免用!=或<> ISNULL或IS NOT NULL、IN ,NOT IN等這樣的操作符,因為這會使系統無法使用索引,而只能直接搜索表中的數據。例如:
SELECT C1 FROM T1 WHERE C1 != 'B%'
2. 合理使用EXISTS,NOT EXISTS子句。如下所示:
1)SELECT SUM(T1.C1)FROM T1 WHERE((SELECTCOUNT(1)FROM T2 WHERE T2.C2=T1.C2)>0)
2)SELECT SUM(T1.C1) FROM T1WHERE EXISTS( SELECT 1 FROM T2 WHERET2.C2=T1.C2)兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如:
IF (SELECT COUNT(1) FROM table_name WHEREcolumn_name = 'xxx')>0
可以寫成:
IF EXISTS (SELECT 1 FROM table_name WHEREcolumn_name = 'xxx')
3. 經常需要寫一個T_SQL語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:
1) SELECTa.C1 FROM T1 a
WHERE NOT EXISTS (SELECT 1 FROM T2 b WHERE a.C1= b.C1)
2) SELECT a.C1 FROM T1 a
LEFT JOIN T2 b ON a.C1 = b.C1 WHERE b.C1IS NULL
3) SELECT a.C1 FROM T1 a
WHERE a.C1 NOT IN (SELECT C1 FROM T2)
三種寫法都可以得到同樣正確的結果,但是效率依次降低。
4. 能夠用BETWEEN的就不要用IN
SELECT * FROM T1 WHERE ID IN (10,11,12,13,14)
改成:
SELECT* FROM T1 WHERE ID BETWEEN 10 AND 14
因為IN會使系統無法使用索引,而只能直接搜索表中的數據。

⑻ 怎樣給訪問量過大的mysql資料庫減壓

以MySQL為例,碎片的存在十分影響性能

MySQL 的碎片是 MySQL 運維過程中比較常見的問題,碎片的存在十分影響資料庫的性能,本文將對 MySQL 碎片進行一次講解。


判斷方法:

MySQL 的碎片是否產生,通過查看

show table status from table_nameG;

這個命令中 Data_free 欄位,如果該欄位不為 0,則產生了數據碎片。


產生的原因:

1. 經常進行 delete 操作

經常進行 delete 操作,產生空白空間,如果進行新的插入操作,MySQL將嘗試利用這些留空的區域,但仍然無法將其徹底佔用,久而久之就產生了碎片;


演示:

創建一張表,往裡面插入數據,進行一個帶有 where 條件或者 limit 的 delete 操作,刪除前後對比一下 Data_free 的變化。

刪除前:

Data_free 不為 0,說明有碎片;


2. update 更新

update 更新可變長度的欄位(例如 varchar 類型),將長的字元串更新成短的。之前存儲的內容長,後來存儲是短的,即使後來插入新數據,那麼有一些空白區域還是沒能有效利用的。

演示:

創建一張表,往裡面插入一條數據,進行一個 update 操作,前後對比一下 Data_free 的變化。

CREATE TABLE `t1` ( `k` varchar(3000) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

更新語句:update t1 set k='aaa';

更新前長度:223 Data_free:0

更新後長度:3 Data_free:204

Data_free 不為 0,說明有碎片;


產生影響:

1. 由於碎片空間是不連續的,導致這些空間不能充分被利用;

2. 由於碎片的存在,導致資料庫的磁碟 I/O 操作變成離散隨機讀寫,加重了磁碟 I/O 的負擔。


清理辦法:

  • MyISAM:optimize table 表名;(OPTIMIZE 可以整理數據文件,並重排索引)

  • Innodb:

  • 1. ALTER TABLE tablename ENGINE=InnoDB;(重建表存儲引擎,重新組織數據)

    2. 進行一次數據的導入導出

    碎片清理的性能對比:

    引用我之前一個生產庫的數據,對比一下清理前後的差異。

    SQL執行速度:

  • select count(*) from test.twitter_11;


  • 修改前:1 row in set (7.37 sec)

    修改後:1 row in set (1.28 sec)

    結論:

    通過對比,可以看到碎片清理前後,節省了很多空間,SQL執行效率更快。所以,在日常運維工作中,應對碎片進行定期清理,保證資料庫有穩定的性能。

⑼ 如何讓sql2000資料庫阻止某IP訪問 或者有軟體可以阻止

有幾種辦法
1.更改sql2000的默認埠。
2.修改密碼。
3.直接在windows的防火牆中設置 sql2000的埠只能讓那些ip訪問

⑽ 關於SQL資料庫優化

具體要注意的:
1.應盡量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0
2.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜索該表的所有行。
3.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
4.in 和 not in 也要慎用,因為IN會使系統無法使用索引,而只能直接搜索表中的數據。如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
5.盡量避免在索引過的字元數據中,使用非打頭字母搜索。這也使得引擎無法利用索引。
見如下例子:
SELECT * FROM T1 WHERE NAME LIKE 『%L%』
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=』L』
SELECT * FROM T1 WHERE NAME LIKE 『L%』
即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有數據逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。
6.必要時強制查詢優化器使用某個索引,如在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變數,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
7.應盡量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
SELECT * FROM T1 WHERE F1/2=100
應改為:
SELECT * FROM T1 WHERE F1=100*2
SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=』5378』
應改為:
SELECT * FROM RECORD WHERE CARD_NO LIKE 『5378%』
SELECT member_number, first_name, last_name FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
應改為:
SELECT member_number, first_name, last_name FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何對列的操作都將導致表掃描,它包括資料庫函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。
8.應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--『2005-11-30』生成的id
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
9.不要在 where 子句中的「=」左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
10.在使用索引欄位作為條件時,如果該索引是復合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓欄位順序與索引順序相一致。
11.很多時候用 exists是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select top 1 from b where num=a.num)
SELECT SUM(T1.C1)FROM T1 WHERE(
(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
SELECT SUM(T1.C1) FROM T1WHERE EXISTS(
SELECT * FROM T2 WHERE T2.C2=T1.C2)
兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。
如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
可以寫成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
經常需要寫一個T_SQL語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:
SELECT a.hdr_key FROM hdr_tbl a---- tbl a 表示tbl用別名a代替
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
SELECT a.hdr_key FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL
SELECT hdr_key FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
三種寫法都可以得到同樣正確的結果,但是效率依次降低。
12.盡量使用表變數來代替臨時表。如果表變數包含大量數據,請注意索引非常有限(只有主鍵索引)。
13.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
14.臨時表並不是不可使用,適當地使用它們可以使某些常式更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。
15.在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然後insert。
16.如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

17.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。
18.盡量避免大事務操作,提高系統並發能力。
19.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

20. 避免使用不兼容的數據類型。例如float和int、char和varchar、binary和varbinary是不兼容的。數據類型的不兼容可能使優化器無法執行一些本來可以進行的優化操作。例如:
SELECT name FROM employee WHERE salary > 60000
在這條語句中,如salary欄位是money型的,則優化器很難對其進行優化,因為60000是個整型數。我們應當在編程時將整型轉化成為錢幣型,而不要等到運行時轉化。
21.充分利用連接條件,在某種情況下,兩個表之間可能不只一個的連接條件,這時在 WHERE 子句中將連接條件完整的寫上,有可能大大提高查詢速度。
例:
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO
第二句將比第一句執行快得多。
22、使用視圖加速查詢
把表的一個子集進行排序並創建視圖,有時能加速查詢。它有助於避免多重排序 操作,而且在其他方面還能簡化優化器的工作。例如:
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>「98000」
ORDER BY cust.name
如果這個查詢要被執行多次而不止一次,可以把所有未付款的客戶找出來放在一個視圖中,並按客戶的名字進行排序:
CREATE VIEW DBO.V_CUST_RCVLBES
AS
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
ORDER BY cust.name
然後以下面的方式在視圖中查詢:
SELECT * FROM V_CUST_RCVLBES
WHERE postcode>「98000」
視圖中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁碟I/O,所以查詢工作量可以得到大幅減少。
23、能用DISTINCT的就不用GROUP BY
SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID
可改為:
SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10
24.能用UNION ALL就不要用UNION
UNION ALL不執行SELECT DISTINCT函數,這樣就會減少很多不必要的資源

35.盡量不要用SELECT INTO語句。
SELECT INOT 語句會導致表鎖定,阻止其他用戶訪問該表。
上面我們提到的是一些基本的提高查詢速度的注意事項,但是在更多的情況下,往往需要反復試驗比較不同的語句以得到最佳方案。最好的方法當然是測試,看實現相同功能的SQL語句哪個執行時間最少,但是資料庫中如果數據量很少,是比較不出來的,這時可以用查看執行計劃,即:把實現相同功能的多條SQL語句考到查詢分析器,按CTRL+L看查所利用的索引,表掃描次數(這兩個對性能影響最大),總體上看詢成本百分比即可。

今天在itput上看了一篇文章,是討論一個語句的優化:
原貼地址: http://www.itpub.net/viewthread.php?tid=1015964&extra=&page=1
一,發現問題 優化的語句:
請問以下語句如何優化:
CREATE TABLE aa_001
( ip VARCHAR2(28),
name VARCHAR2(10),
password VARCHAR2(30) )

select * from aa_001 where ip in (1,2,3) order by name desc;
--目前表中記錄有一千多萬條左右,而且in中的值個數是不確定的。
以上就是優化的需要優化的語句和情況。

不少人在後面跟帖:有的說沒辦法優化,有的說將IN該為EXISTS,有的說在ip上建立索引復合索引(ip,name)等等。
二,提出問題 那這樣的情況,能優化嗎,如何優化?今天就來討論這個問題。
三,分析問題 1,數據量1千萬多條。
2,in中的值個數是不確定
3.1 分析數據分布 這里作者沒有提到ip列的數據的分布情況,目前ip列的數據分布可能有以下幾種:
1,ip列(數據唯一,或者數據重復的概率很小)
2,ip列 (數據不均勻,可能有些數據重復多,有些重復少)
3,ip列 (數據分布比較均勻,數據大量重復,主要就是一些同樣的數據(可能只有上萬級別不同的ip數據等)

解決問題:
1,對於第一種數據分布情況,只要在ip列建立一個索引即可。這時不管表有多少行, in個數是不確定的情況下,都很快。
2,對應第二中數據分布情況,在ip列建立索引,效果不好。因為數據分布不均勻,可能有些快,有些慢
3,對應第三種數據分布情況,在ip列建立索引,速度肯定慢。
注意:這里的 order by name desc 是在取出數據後再排序的。而不是取數據前排序

對於2,3兩個情況,因為都是可能需要取出大量的數據,優化器就採用表掃描(table scan),而不是索引查找(index seek) ,速度很慢,因為這時表掃描效率要優於索引查找,特別是高並發情況下,效率很低。

那對應2,3中情況,如何處理。是將in改成exists。其實在sql server 2005和oracle里的優化器在in後面數據少時,效率是一樣的。這時採用一般的索引效率很低。這時如果在ip列上建立聚集索引,效率會比較高。我們在SQL server 2005中做個測試。

表:[dbo].[[zping.com]]]中有約200萬條數據。包含列Userid, id, Ruleid等列。按照上面的情況查詢一下類似語句:
select * from [dbo].[[zping.com]]] where
userid in ('',''
,'') order by Ruleid desc

我們先看userid的數據分布情況,執行下面語句:
select userid,count(*) from [dbo].[[zping.com]]] group by userid order by 2
這時我們看看數據分布:總共有379條數據,數據兩從1到15萬都有,數據分布傾斜嚴重。下圖是其中一部分。

這時如果在ip上建立非聚集索引,效率很低,而且就是強行索引掃描,效率也很低,會發現IO次數比表掃描還高。這時只能在ip上建立聚集索引。這時看看結果。

這時發現,搜索採用了(clustered index seek)聚集搜索掃描。
在看看查詢返回的結果:
(156603 行受影響)
表 '[zping.com]'。掃描計數 8,邏輯讀取 5877 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 'Worktable'。掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
返回15萬行,才不到6千次IO。效率較高,因為這15萬行要排序,查詢成本里排序佔了51%。當然可以建立(userid,Ruleid)復合聚集索引,提高性能,但這樣做DML維護成本較高。建議不採用。

從上面的測試例子可以看出, 優化的解決辦法:
數據分布為1:建立ip索引即可
數據分布為2,3:在ip列建立聚集索引。