⑴ 千萬級資料庫多表查詢解決方案
1. 建立合理的索引,避免掃描多餘數據,避免表掃描!
2.使用子查詢為確保消除重復值,必須為外部查詢的每個結果都處理嵌套查詢。在這種情況下可以考慮用聯接查詢來取代。
3.用EXISTS替代IN、用NOT EXISTS替代NOT IN。因為EXISTS引入的子查詢只是測試是否存在符合子查詢中指定條件的行,效率較高。無論在哪種情況下,NOT IN都是最低效的。因為它對子查詢中的表執行了一個全表遍歷。
⑵ 千萬級數據
資料庫吧,你用什麼資料庫
mysql可以配合lucene做搜索引擎,還不夠大可以用cluster.一般你用like沒問題,索引要做得好。
如果大家有異議,可以在後面補充。我會隨時更新的。
現在大概列出如下:(望各位補充)
1.資料庫的設計
盡量把資料庫設計的更小的占磁碟空間.
1).盡可能使用更小的整數類型.(mediumint就比int更合適).
2).盡可能的定義欄位為not null,除非這個欄位需要null.(這個規則只適合欄位為KEY的情形)
3).如果沒有用到變長欄位的話比如varchar,那就採用固定大小的紀錄格式比如char.(CHAR 總是比VARCHR快)
4).表的主索引應該盡可能的短.這樣的話每條紀錄都有名字標志且更高效.
5).只創建確實需要的索引。索引有利於檢索記錄,但是不利於快速保存記錄。如果總是要在表的組合欄位上做搜索,那麼就在這些欄位上創建索引。索引的第一部分必須是最常使用的欄位.如果總是需要用到很多欄位,首先就應該多復制這些欄位,使索引更好的壓縮。
(這條只適合MYISAM引擎的表,對於INNODB則在保存記錄的時候關系不大,因為INNODB是以事務為基礎的,如果想快速保存記錄的話,特別是大批量的導入記錄的時候)
6).所有數據都得在保存到資料庫前進行處理。
7).所有欄位都得有默認值。
8).在某些情況下,把一個頻繁掃描的表分成兩個速度會快好多。在對動態格式表掃描以取得相關記錄時,它可能使用更小的靜態格式表的情況下更是如此。
(具體的表現為:MYISAM表的MERGE類型,以及MYISAM和INNODB通用的分區,詳情見手冊)
9).不會用到外鍵約束的地方盡量不要使用外鍵。
2.系統的用途
1).及時的關閉對MYSQL的連接。
2).explain 復雜的SQL語句。(這樣能確定你的SELECT 語句怎麼優化最佳)
3).如果兩個關聯表要做比較話,做比較的欄位必須類型和長度都一致.(在數據龐大的時候建立INDEX)
4).LIMIT語句盡量要跟order by或者 distinct.這樣可以避免做一次full table scan.
5).如果想要清空表的所有紀錄,建議用truncate table tablename而不是delete from tablename.
不過有一個問題,truncate 不會在事務處理中回滾。因為她要調用create table 語句。
(Truncate Table 語句先刪除表然後再重建,這個是屬於文件界別的,所以自然快N多)
實測例子:
song2為INNODB表。
mysql> select count(1) from song2;
+----------+
| count(1) |
+----------+
| 500000 |
+----------+
1 row in set (0.91 sec)
mysql> delete from song2;
Query OK, 500000 rows affected (15.70 sec)
mysql> truncate table song2;
Query OK, 502238 rows affected (0.17 sec)
mysql>
{
這一點手冊上有詳細解釋:
13.2.9. TRUNCATE語法
TRUNCATE [TABLE] tbl_name
TRUNCATE TABLE用於完全清空一個表。從邏輯上說,該語句與用於刪除所有行的DELETE語句等同,但是在有些情況下,兩者在使用上有所不同。
對於InnoDB表,如果有需要引用表的外鍵限制,則TRUNCATE TABLE被映射到DELETE上;否則使用快速刪減(取消和重新創建表)。使用TRUNCATE TABLE重新設置AUTO_INCREMENT計數器,設置時不考慮是否有外鍵限制。
對於其它存儲引擎,在MySQL 5.1中,TRUNCATE TABLE與DELETE FROM有以下幾處不同:
· 刪減操作會取消並重新創建表,這比一行一行的刪除行要快很多。
· 刪減操作不能保證對事務是安全的;在進行事務處理和表鎖定的過程中嘗試進行刪減,會發生錯誤。
· 被刪除的行的數目沒有被返回。
· 只要表定義文件tbl_name.frm是合法的,則可以使用TRUNCATE TABLE把表重新創建為一個空表,即使數據或索引文件已經被破壞。
· 表管理程序不記得最後被使用的AUTO_INCREMENT值,但是會從頭開始計數。即使對於MyISAM和InnoDB也是如此。MyISAM和InnoDB通常不再次使用序列值。
· 當被用於帶分區的表時,TRUNCATE TABLE會保留分區;即,數據和索引文件被取消並重新創建,同時分區定義(.par)文件不受影響。
TRUNCATE TABLE是在MySQL中採用的一個Oracle SQL擴展。
}
6).能使用STORE PROCEDURE 或者 USER FUNCTION的時候.(ROUTINE總是減少了伺服器端的開銷)
7).在一條insert語句中採用多重紀錄插入格式.而且使用load data infile來導入大量數據,這比單純的indert快好多.(在MYSQL中具體表現為:INSERT INTO TABLEQ VALUES (),(),...();)
(還有就是在MYISAM表中插入大量記錄的時候先禁用到KEYS後面再建立KEYS,具體表現語句:
ALTER TABLE TABLE1 DISABLE KEYS;ALTER TABLE TABLE1 ENABLE KEYS;
而對於INNNODB 表在插入前先 set autocommit=0;完了後:set autocommit=1;這樣效率比較高。)
8).經常OPTIMIZE TABLE 來整理碎片.
9).還有就是date 類型的數據如果頻繁要做比較的話盡量保存在unsigned int 類型比較快。
3.系統的瓶頸
1).磁碟搜索.
並行搜索,把數據分開存放到多個磁碟中,這樣能加快搜索時間.
2).磁碟讀寫(IO)
可以從多個媒介中並行的讀取數據。
3).CPU周期
數據存放在主內存中.這樣就得增加CPU的個數來處理這些數據。
4).內存帶寬
當CPU要將更多的數據存放到CPU的緩存中來的話,內存的帶寬就成了瓶頸.
====
Another article more about tuning details:
http://www.informit.com/articles/article.aspx?p=29406&seqNum=1
http://blog.chinaunix.net/u/29134/showart_264480.html
⑶ MySQL資料庫千萬級數據處理
資料庫主要抄就是兩個功能,襲一個是查詢,一個是儲存,而大數據必定會拖慢查詢,我們對於大數據,更多的是從業務邏輯進行拆分,比如:
當存儲一個人的歷史信息的時候,可以按照時間存儲,一定是最近的記錄最經常訪問,這就是我們常說的二八定律,最長訪問的數據僅僅佔有不到兩成的數據量。
上面說的就是分庫分表,這是一種解決數據量大的辦法。
內存資料庫,redis也是一種處理大數據的辦法,將常訪問的數據放到redis裡面,可以緩解資料庫的壓力,還是像上面說的,我們只要可以找到用戶經常訪問的數據,然後放到內存資料庫中,就可以大大減少mysql的壓力。
最後,技術一定是為解決問題而產生的,我們一定需要對業務進行分析,才能考慮使用什麼技術,拋開業務單存講技術,這是不正確的。