對mysql優(yōu)化時(shí)一個(gè)綜合性的技術(shù),主要包括 a: 表的設(shè)計(jì)合理化(符合3NF) b: 添加適當(dāng)索引(index) [四種: 普通索引、主鍵索引、唯一索引unique、全文索引] c: 分表技術(shù)(水平分割、垂直分割) d: 讀寫[寫: update/delete/add]分離 e: 存儲(chǔ)過程 [模塊化編程,可以提高速度] f: 對mysql配置優(yōu)化 [配置最大并發(fā)數(shù)my.ini, 調(diào)整緩存大小 ] g: mysql服務(wù)器硬件升級 h: 定時(shí)的去清除不需要的數(shù)據(jù),定時(shí)進(jìn)行碎片整理(MyISAM) u什么樣的表才是符合3NF (范式) 表的范式,是首先符合1NF, 才能滿足2NF , 進(jìn)一步滿足3NF 1NF: 即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只有數(shù)據(jù)庫是關(guān)系型數(shù)據(jù)庫(mysql/oracle/db2/informix/sysbase/sql server),就自動(dòng)的滿足1NF ? 數(shù)據(jù)庫的分類 關(guān)系型數(shù)據(jù)庫: mysql/oracle/db2/informix/sysbase/sql server 非關(guān)系型數(shù)據(jù)庫: (特點(diǎn): 面向?qū)ο蠡蛘呒? NoSql數(shù)據(jù)庫: MongoDB(特點(diǎn)是面向文檔) 2NF: 表中的記錄是唯一的, 就滿足2NF, 通常我們設(shè)計(jì)一個(gè)主鍵來實(shí)現(xiàn) 3NF: 即表中不要有冗余數(shù)據(jù), 就是說,表的信息,如果能夠被推導(dǎo)出來,就不應(yīng)該單獨(dú)的設(shè)計(jì)一個(gè)字段來存放. 比如下面的設(shè)計(jì)就是不滿足3NF: 反3NF : 但是,沒有冗余的數(shù)據(jù)庫未必是最好的數(shù)據(jù)庫,有時(shí)為了提高運(yùn)行效率,就必須降低范式標(biāo)準(zhǔn),適當(dāng)保留冗余數(shù)據(jù)。具體做法是: 在概念數(shù)據(jù)模型設(shè)計(jì)時(shí)遵守第三范式,降低范式標(biāo)準(zhǔn)的工作放到物理數(shù)據(jù)模型設(shè)計(jì)時(shí)考慮。降低范式就是增加字段,允許冗余。 案例 : Sql語句本身的優(yōu)化 問題是: 如何從一個(gè)大項(xiàng)目中,迅速的定位執(zhí)行速度慢的語句. (定位慢查詢) ①首先我們了解mysql數(shù)據(jù)庫的一些運(yùn)行狀態(tài)如何查詢(比如想知道當(dāng)前mysql運(yùn)行的時(shí)間/一共執(zhí)行了多少次select/update/delete.. / 當(dāng)前連接) show status 常用的: show status like ‘uptime’ ; show stauts like ‘com_select’ show stauts like ‘com_insert’ ...類推 update delete ? show [session|global] status like .... 如果你不寫 [session|global] 默認(rèn)是session 會(huì)話,指取出當(dāng)前窗口的執(zhí)行,如果你想看所有(從mysql 啟動(dòng)到現(xiàn)在,則應(yīng)該 global) show status like ‘connections’; //顯示慢查詢次數(shù) show status like ‘slow_queries’; ②如何去定位慢查詢 構(gòu)建一個(gè)大表(400 萬)-> 存儲(chǔ)過程構(gòu)建 默認(rèn)情況下,mysql認(rèn)為10秒才是一個(gè)慢查詢. l修改mysql的慢查詢. show variables like ‘long_query_time’ ; //可以顯示當(dāng)前慢查詢時(shí)間 set long_query_time=1 ;//可以修改慢查詢時(shí)間 構(gòu)建大表->大表中記錄有要求, 記錄是不同才有用,否則測試效果和真實(shí)的相差大. 創(chuàng)建: CREATE TABLE dept( /*部門表*/ deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*編號*/ dname VARCHAR(20) NOT NULL DEFAULT '', /*名稱*/ loc VARCHAR(13) NOT NULL DEFAULT '' /*地點(diǎn)*/ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; CREATE TABLE emp (empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*編號*/ ename VARCHAR(20) NOT NULL DEFAULT '', /*名字*/ job VARCHAR(9) NOT NULL DEFAULT '',/*工作*/ mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上級編號*/ hiredate DATE NOT NULL,/*入職時(shí)間*/ sal DECIMAL(7,2) NOT NULL,/*薪水*/ comm DECIMAL(7,2) NOT NULL,/*紅利*/ deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部門編號*/ )ENGINE=MyISAM DEFAULT CHARSET=utf8 ; CREATE TABLE salgrade ( grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, losal DECIMAL(17,2) NOT NULL, hisal DECIMAL(17,2) NOT NULL )ENGINE=MyISAM DEFAULT CHARSET=utf8; 測試數(shù)據(jù) INSERT INTO salgrade VALUES (1,700,1200); INSERT INTO salgrade VALUES (2,1201,1400); INSERT INTO salgrade VALUES (3,1401,2000); INSERT INTO salgrade VALUES (4,2001,3000); INSERT INTO salgrade VALUES (5,3001,9999); 為了存儲(chǔ)過程能夠正常執(zhí)行,我們需要把命令執(zhí)行結(jié)束符修改 delimiter $$ create function rand_string(n INT) returns varchar(255) #該函數(shù)會(huì)返回一個(gè)字符串 begin #chars_str定義一個(gè)變量 chars_str,類型是 varchar(100),默認(rèn)值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ'; declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ'; declare return_str varchar(255) default ''; declare i int default 0; while i < n=""> set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1)); set i = i + 1; end while; return return_str; end $$ 如果希望在程序中使用,是Ok! 創(chuàng)建一個(gè)存儲(chǔ)過程 create procedure insert_emp(in start int(10),in max_num int(10)) begin declare i int default 0; #set autocommit =0 把a(bǔ)utocommit設(shè)置成0 set autocommit = 0; repeat set i = i + 1; insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num()); until i = max_num end repeat; commit; end $$ #調(diào)用剛剛寫好的函數(shù), 1800000條記錄,從100001號開始 call insert_emp(100001,4000000); ③這時(shí)我們?nèi)绻霈F(xiàn)一條語句執(zhí)行時(shí)間超過1秒中,就會(huì)統(tǒng)計(jì)到. ④如果把慢查詢的sql記錄到我們的一個(gè)日志中 在默認(rèn)情況下,我們的mysql不會(huì)記錄慢查詢,需要在啟動(dòng)mysql時(shí)候,指定記錄慢查詢才可以 bin\mysqld.exe - -safe-mode - -slow-query-log [mysql5.5 可以在my.ini指定] bin\mysqld.exe –log-slow-queries=d:/abc.log [低版本mysql5.0可以在my.ini指定] 先關(guān)閉mysql,再啟動(dòng), 如果啟用了慢查詢?nèi)罩?,默認(rèn)把這個(gè)文件放在 my.ini 文件中記錄的位置 #Path to the database root datadir='C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/' ⑤測試,可以看到在日志中就記錄下我們的mysql慢sql語句. 優(yōu)化問題. 通過 explain 語句可以分析,mysql如何執(zhí)行你的sql語句, 這個(gè)工具的使用放一下,一會(huì)說. 添加索引 【小建議: 】 u四種索引(主鍵索引/唯一索引/全文索引/普通索引) 1.添加 1.1主鍵索引添加 當(dāng)一張表,把某個(gè)列設(shè)為主鍵的時(shí)候,則該列就是主鍵索引 create table aaa (id int unsigned primary key auto_increment , name varchar(32) not null defaul ‘’); 這是id 列就是主鍵索引. 如果你創(chuàng)建表時(shí),沒有指定主鍵索引,也可以在創(chuàng)建表后,在添加, 指令: alter table 表名 add primary key (列名); 舉例: create table bbb (id int , name varchar(32) not null default ‘’); alter table bbb add primary key (id); 1.2普通索引 一般來說,普通索引的創(chuàng)建,是先創(chuàng)建表,然后在創(chuàng)建普通索引 比如: create table ccc( id int unsigned, name varchar(32) ) create index 索引名 on 表 (列1,列名2); 1.3創(chuàng)建全文索引 全文索引,主要是針對對文件,文本的檢索, 比如文章, 全文索引針對MyISAM有用. 創(chuàng)建 : CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) )engine=myisam charset utf8; INSERT INTO articles (title,body) VALUES ('MySQL Tutorial','DBMS stands for DataBase ...'), ('How To Use MySQL Well','After you went through a ...'), ('Optimizing MySQL','In this tutorial we will show ...'), ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), ('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL Security','When configured properly, MySQL ...'); 如何使用全文索引: 錯(cuò)誤用法: select * from articles where body like ‘%mysql%’; 【不會(huì)使用到全文索引】 證明: explain select * from articles where body like ‘%mysql%’ 正確的用法是: select * from articles where match(title,body) against(‘database’); 【可以】 ? 說明: 1.在mysql中fulltext 索引只針對 myisam生效 2.mysql自己提供的fulltext針對英文生效->sphinx (coreseek) 技術(shù)處理中文 3.使用方法是 match(字段名..) against(‘關(guān)鍵字’) 4.全文索引一個(gè) 叫 停止詞, 因?yàn)樵谝粋€(gè)文本中,創(chuàng)建索引是一個(gè)無窮大的數(shù),因此,對一些常用詞和字符,就不會(huì)創(chuàng)建,這些詞,稱為停止詞. 1.4唯一索引 ①當(dāng)表的某列被指定為unique約束時(shí),這列就是一個(gè)唯一索引 create table ddd(id int primary key auto_increment , name varchar(32) unique); 這時(shí), name 列就是一個(gè)唯一索引. unique字段可以為NULL,并可以有多NULL, 但是如果是具體內(nèi)容,則不能重復(fù). 主鍵字段,不能為NULL,也不能重復(fù). ②在創(chuàng)建表后,再去創(chuàng)建唯一索引 create table eee(id int primary key auto_increment, name varchar(32)); create unique index 索引名 on 表名 (列表..); 2.查詢索引 desc 表名 【該方法的缺點(diǎn)是: 不能夠顯示索引名.】 show index(es) from 表名 show keys from 表名 3.刪除 alter table 表名 drop index 索引名; 如果刪除主鍵索引。 alter table 表名 drop primary key [這里有一個(gè)小問題] 4.修改 先刪除,再重新創(chuàng)建. u為什么創(chuàng)建索引后,速度就會(huì)變快? 原理示意圖: . u索引使用的注意事項(xiàng) 索引的代價(jià): 1.占用磁盤空間 2.對dml操作有影響,變慢 u在哪些列上適合添加索引? 總結(jié): 滿足以下條件的字段,才應(yīng)該創(chuàng)建索引. a: 肯定在where條經(jīng)常使用 b: 該字段的內(nèi)容不是唯一的幾個(gè)值(sex) c: 字段內(nèi)容不是頻繁變化. u使用索引的注意事項(xiàng) 把dept表中,我增加幾個(gè)部門: alter table dept add index my_ind (dname,loc); // dname 左邊的列,loc就是右邊的列 說明,如果我們的表中有復(fù)合索引(索引作用在多列上), 此時(shí)我們注意: 1,對于創(chuàng)建的多列索引,只要查詢條件使用了最左邊的列,索引一般就會(huì)被使用。 explain select * from dept where loc='aaa'\G 就不會(huì)使用到索引 2,對于使用like的查詢,查詢?nèi)绻恰?aaa’ 不會(huì)使用到索引 ‘a(chǎn)aa%’ 會(huì)使用到索引。 比如: explain select * from dept where dname like '%aaa'\G 不能使用索引,即,在like查詢時(shí),關(guān)鍵的 ‘關(guān)鍵字’ , 最前面,不能使用 % 或者 _這樣的字符., 如果一定要前面有變化的值,則考慮使用 全文索引->sphinx. 3.如果條件中有or,即使其中有條件帶索引也不會(huì)使用。換言之,就是要求使用的所有字段,都必須建立索引, 我們建議大家盡量避免使用or 關(guān)鍵字 select * from dept where dname=’xxx’ or loc=’xx’ or deptno=45 4.如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號引用起來。否則不使用索引。(添加時(shí),字符串必須’’), 也就是,如果列是字符串類型,就一定要用 ‘’ 把他包括起來. 5.如果mysql估計(jì)使用全表掃描要比使用索引快,則不使用索引。 explain 可以幫助我們在不真正執(zhí)行某個(gè)sql語句時(shí),就執(zhí)行mysql怎樣執(zhí)行,這樣利用我們?nèi)シ治鰏ql指令. u如何查看索引使用的情況: show status like ‘Handler_read%’; 大家可以注意: handler_read_key:這個(gè)值越高越好,越高表示使用索引查詢到的次數(shù)。 handler_read_rnd_next:這個(gè)值越高,說明查詢低效。 usql語句的小技巧 1.在使用group by 分組查詢是,默認(rèn)分組后,還會(huì)排序,可能會(huì)降低速度. 比如: 在group by 后面增加 order by null 就可以防止排序. 2.有些情況下,可以使用連接來替代子查詢。因?yàn)槭褂胘oin,MySQL不需要在內(nèi)存中創(chuàng)建臨時(shí)表。 select * from dept, emp where dept.deptno=emp.deptno; [簡單處理方式] select * from dept left join emp on dept.deptno=emp.deptno; [左外連接,更ok!] u如何選擇mysql的存儲(chǔ)引擎 在開發(fā)中,我們經(jīng)常使用的存儲(chǔ)引擎 myisam / innodb/ memory myisam 存儲(chǔ): 如果表對事務(wù)要求不高,同時(shí)是以查詢和添加為主的,我們考慮使用myisam存儲(chǔ)引擎. ,比如 bbs 中的 發(fā)帖表,回復(fù)表. INNODB 存儲(chǔ): 對事務(wù)要求高,保存的數(shù)據(jù)都是重要數(shù)據(jù),我們建議使用INNODB,比如訂單表,賬號表. 問 MyISAM 和 INNODB的區(qū)別 1. 事務(wù)安全 2. 查詢和添加速度 3. 支持全文索引 4. 鎖機(jī)制 5. 外鍵 MyISAM 不支持外鍵, INNODB支持外鍵. (在PHP開發(fā)中,通常不設(shè)置外鍵,通常是在程序中保證數(shù)據(jù)的一致) Memory 存儲(chǔ),比如我們數(shù)據(jù)變化頻繁,不需要入庫,同時(shí)又頻繁的查詢和修改,我們考慮使用memory, 速度極快. u如果你的數(shù)據(jù)庫的存儲(chǔ)引擎是myisam,請一定記住要定時(shí)進(jìn)行碎片整理 舉例說明: create table test100(id int unsigned ,name varchar(32))engine=myisam; insert into test100 values(1,’aaaaa’); insert into test100 values(2,’bbbb’); insert into test100 values(3,’ccccc’); 我們應(yīng)該定義對myisam進(jìn)行整理 optimize table test100; mysql_query(“optimize tables $表名”); 技術(shù)就是窗戶紙.->經(jīng)常和技術(shù)好人。 uPHP定時(shí)完成數(shù)據(jù)庫的備份 ①手動(dòng)備份數(shù)據(jù)庫(表的)方法 cmd控制臺: mysqldump –u root –proot 數(shù)據(jù)庫 [表名1 表名2..] > 文件路徑 比如: 把temp數(shù)據(jù)庫備份到 d:\temp.bak mysqldump –u root –proot temp > d:\temp.bak 如果你希望備份是,數(shù)據(jù)庫的某幾張表 mysqldump –u root –prot temp dept > d:\temp.dept.bak 如何使用備份文件恢復(fù)我們的數(shù)據(jù). mysql控制臺 source d:\temp.dept.bak ②使用定時(shí)器來自定完成 把備份數(shù)據(jù)庫的指令,寫入到 bat文件, 然后通過任務(wù)管理器去定時(shí)調(diào)用 bat文件. mytask.bat 內(nèi)容是: C:\myenv\mysql5.5.27\bin\mysqldump -u root -proot temp dept > d:\temp.dept.bak ? 如果你的mysqldump.exe文件路徑有空格,則一定要使用 “” 包括. 把mytask.bat 做成一個(gè)任務(wù),并定時(shí)調(diào)用在 2:00 調(diào)用一次 步驟 任務(wù)計(jì)劃->增加一個(gè)任務(wù),選中你的mytask.bat文件 ,最后配置: 測試ok 現(xiàn)在問題是,每次都是覆蓋原來的備份文件,不利用我們分時(shí)間段進(jìn)行備份, 我們可以這樣處理; 示意圖: 代碼是: mytask2.bat 內(nèi)容: C:\myenv\php-5.3.5\php.exe C:\myenv\apache\htdocs\mytask.php mytask.php代碼: <> //定時(shí)備份我們的數(shù)據(jù)庫文件 date_default_timezone_set('PRC'); $bakfilename=date('YmdHis',time()); $command='C:\myenv\mysql5.5.27\bin\mysqldump -u root -proot temp dept > d:\\{$bakfilename}'; exec($command); 最后測試ok! 作用是,寫一個(gè)數(shù)據(jù)庫, 數(shù)據(jù)庫中有三張表,然后每天 2:00 備份一次,文件名以時(shí)間來命名. 測試. u使用PHP完成定時(shí)發(fā)送郵件的功能 ①看一個(gè)實(shí)際的需求 ②設(shè)計(jì)一張郵件表 create table maillist (id int unsigned primary key auto_increment, getter varchar(64) not null default '', sender varchar(64) not null default '', title varchar(32) not null default '', content varchar(2048) not null default '', sendtime int unsigned not null default 0, flag tinyint unsigned not null default 0)engine=myisam charset utf8; insert into maillist values(null,'hsp@itcast.cn','hanshunping@tsinghua.org.cn','hello100','abc hello',unix_timestamp()+10*3600,0); insert into maillist values(null,'hsp@itcast.cn','hanshunping@tsinghua.org.cn','hello200','abc hello200',unix_timestamp()+10*3600,0); ③寫代碼 1.怎樣可以定時(shí)的去檢索哪些郵件該發(fā)送., 只能每隔一定時(shí)間(1min)就看看哪些郵件該發(fā)送, mailtask.php 2.上面的代碼是模擬發(fā)送郵件,看看如何真正發(fā)送郵件. 在PHP中,有一個(gè)函數(shù) mail , 是用于發(fā)送郵件,我們實(shí)際上可以使用 PHPMailer 類,我們使用他完成. l要正確的使用PHPMailer 發(fā)送郵件,需要滿足如下條件 1.本身機(jī)器是可以聯(lián)網(wǎng)的 2.需要搭建自己的smtp郵件服務(wù)器->示意圖 3.搭建自己的郵件服務(wù)器. 卸載. 安裝時(shí)傻瓜式的,一步一步的走ok 配置 : 3.1選擇access數(shù)據(jù)庫 3.2 3.3配置郵件服務(wù)器 點(diǎn)擊設(shè)置->郵箱域名設(shè)置 點(diǎn)擊設(shè)置->服務(wù)器設(shè)置 設(shè)置一個(gè)賬號(試用版本只能設(shè)置5個(gè)賬號) 代碼: <> // 練習(xí)用PHPmailer發(fā)送郵件 require('./PHPMailer/class.phpmailer.php'); $mailer = new PHPMailer(); /* from 來自于誰 to :寄給誰 cc : 抄送 subject: 郵件主題 Body: 郵件正文 // 發(fā)送怎么發(fā) ? */ $cont = <> hello,world yyy!; EMAIL; // echo $cont;exit; $mailer->CharSet = 'utf-8'; $mailer->ContentType = 'text/html'; // 設(shè)置內(nèi)容類型為html,這樣charset才能發(fā)揮作用 $mailer->Encoding = 'base64'; // 防止服務(wù)器中繼時(shí),服務(wù)器能接收的編碼不一致,帶來問題. $mailer->From = 'shunping@192.168.1.152'; $mailer->FromName = '順平'; $mailer->Subject = '一份問候,你好,word'; $mailer->Body = $cont; // 設(shè)置一下語言包 $mailer->SetLanguage('zh_cn'); // 增加收件人地址 // $mailer->AddAddress('328268186@qq.com','saozi'); $mailer->AddAddress('hanshunping@tsinghua.org.cn','shunping'); if($mailer->Send()) { echo '發(fā)送okok'; } else{ echo 'fail '; } 配置 php.ini 啟用賬號 shunping@192.168.1.152 [mail function] ; For Win32 only. ; http:///smtp SMTP = localhost ; http:///smtp-port smtp_port = 25 ; For Win32 only. ; http:///sendmail-from sendmail_from = shunping@192.168.1.152 測試一把 成功! 如何在linux下完成定時(shí)任務(wù): linux如何備份. 1. 直接執(zhí)行PHP腳本, 需要在同一個(gè)服務(wù)器上執(zhí)行. # crontab -e 00 * * * * /usr/local/bin/php /home/htdocs/phptimer.php 2.通過HTTP請求來觸發(fā)腳本, PHP文件允許不在同一服務(wù)器上 # crontab -e 00 * * * * /usr/bin/wget -q -O temp.txt http://www./phptimer.php 上面是通過wget來請求PHP文件, PHP輸出會(huì)保存在臨時(shí)文件temp.txt中 # crontab -e 00 * * * * /usr/bin/curl -o temp.txt http://www./phptimer.php 上面是通過curl -o來請求PHP文件, PHP輸出會(huì)保存在臨時(shí)文件temp.txt中 # crontab -e 00 * * * * lynx -dump http://www./phptimer.php 上面是通過Lynx文本瀏覽器來請求PHP文件 n分表技術(shù) 分表技術(shù)有(水平分割和垂直分割) 當(dāng)一張?jiān)絹碓酱髸r(shí)候,即使添加索引還慢的話,我們可以使用分表 以qq用戶表來具體的說明一下分表的操作. 思路如圖 : 首先我創(chuàng)建三張表 user0 / user1 /user2 , 然后我再創(chuàng)建 uuid表,該表的作用就是提供自增的id, 走代碼: create table user0( id int unsigned primary key , name varchar(32) not null default '', pwd varchar(32) not null default '') engine=myisam charset utf8; create table user1( id int unsigned primary key , name varchar(32) not null default '', pwd varchar(32) not null default '') engine=myisam charset utf8; create table user2( id int unsigned primary key , name varchar(32) not null default '', pwd varchar(32) not null default '') engine=myisam charset utf8; create table uuid( id int unsigned primary key auto_increment)engine=myisam charset utf8; 編寫addUser.php <> //注冊一個(gè)用戶 $con=mysql_connect('localhost','root','root'); if(!$con){ die('連接失敗!'); } mysql_select_db('temp',$con); $name=$_GET['name']; $pwd=$_GET['pwd']; //這時(shí)我們先獲取用戶id,id是從uuid表獲取 $sql='insert into uuid values(null)'; if(mysql_query($sql,$con)){ $id=mysql_insert_id(); } //計(jì)算表名,就是,你應(yīng)該把這個(gè)用戶放入到哪個(gè)表 $talname='user'.$id%3; $sql='insert into {$talname} values ($id,'$name','$pwd')'; if(mysql_query($sql,$con)){ echo '添加用戶到 '.$talname.'ok'; } mysql_close($con); // <> //注冊一個(gè)用戶 $con=mysql_connect('localhost','root','root'); if(!$con){ die('連接失敗!'); } mysql_select_db('temp',$con); $id=intval($_GET['id']); //計(jì)算表名 $tabname='user'.$id%3; $sql='select pwd from {$tabname} where id=$id'; $res=mysql_query($sql,$con); if($row=mysql_fetch_assoc($res)){ echo '在{$tabname}. 中發(fā)現(xiàn) id號為 {$id}'; } //..... 思考: 如果我們做的是一個(gè)平安保險(xiǎn)公司的一個(gè)訂單(8999999999000000條)查詢功能更. ,如何處理海量表?->按時(shí)間. 1.分表的標(biāo)準(zhǔn)是依賴業(yè)務(wù)邏輯(時(shí)間/地區(qū)/....) 2.安裝字符不同. a-z 3.我們給用戶提供的查詢界面一定是有條件,不能讓用戶進(jìn)行大范圍.(世界),如果需要的可以根據(jù)不同的規(guī)則,對應(yīng)多套分表. 4.檢索時(shí)候,帶分頁條件,減少返回的數(shù)據(jù). 5.項(xiàng)目中,靈活的根據(jù)需求來考慮. n垂直分割 示意圖: 一句話: 如果一張表某個(gè)字段,信息量大,但是我們很少查詢,則可以考慮把這些字段,單獨(dú)的放入到一張表中,這種方式稱為垂直分割. |
|