一、模版修改
在導(dǎo)出表時(shí),powerdesigner默認(rèn)為我們提供了很多的模版,在工具欄中選擇【Report--->Report Template】即可看到所有的默認(rèn)模版。如圖一:
圖一 模版列表
這里我們?yōu)榱藢?dǎo)出powerdesigner中創(chuàng)建的表,在工具欄中選擇【Report--->Reports】(快捷鍵Ctrl+E),然后創(chuàng)建一個(gè)New Report,如下圖二所以,選擇Standard Physical Report,這里選擇的標(biāo)準(zhǔn)的模版,點(diǎn)擊OK確定。
圖二 創(chuàng)建新的Report
從工具欄【Report--->Print Preview】或者點(diǎn)擊圖標(biāo)同樣可以預(yù)覽導(dǎo)出到word的效果了。效果如圖三所示:
圖三 導(dǎo)出到word中預(yù)覽效果
從【圖三】中的工具欄里面HTM和RTF兩種導(dǎo)出格式。如果導(dǎo)出到word選擇RTF格式即可,但是我們從【圖三】中看出紅色標(biāo)出的部分,1 是word的頁(yè)眉,同樣還有頁(yè)腳信息 ,2 是一些列的屬性清單。
圖四 設(shè)置頁(yè)眉、頁(yè)腳
在【圖四】中,選擇Header/Footer后,刪掉Header里面的%MODULE% %MODELNAME%,刪掉Footer里面的%APPNAME% %DATE% 頁(yè)數(shù) %PAGE%,User_defined footer就會(huì)自動(dòng)勾上,這樣就去掉了頁(yè)眉、頁(yè)腳了
還有其他的比如表前面的自增序號(hào),第一頁(yè)中的創(chuàng)建者、版本、日期信息也不需要,我們可以進(jìn)行配置去掉,如下【圖五】【圖六】
圖四
圖五 Properties配置
在圖五中,在默認(rèn)配置中(General)勾上No paragraph numbering即可取消表前面的自增序號(hào),在Title Page中選擇 No Title Page就不會(huì)生成第一頁(yè)中關(guān)于創(chuàng)建者、版本、日期等信息。
在【圖三】中,預(yù)覽看到的內(nèi)容太多,就必須刪除一些我們不需要的內(nèi)容,經(jīng)過(guò)刪減之后,如下【圖六】所示
圖六
在【圖六】中右鍵單擊【List of Table Columns - 表<%PARENT%>列說(shuō)明】,從菜單中選擇 Edit Title...,就可以編輯成現(xiàn)在我們已看到的。然后,在右鍵菜單中選擇Layout...,選擇我們所需要顯示的內(nèi)容,Code表示列名稱,一般用英文單詞或拼音字母表示,Name一般用中文描述,Data Type 表示數(shù)據(jù)類型,Comment表示字段備注或字段說(shuō)明等。
到此基本上已經(jīng)完成了powerdesigner模版的修改
二、導(dǎo)出表
然后點(diǎn)擊[Report---->Generate RTF]導(dǎo)出到word中,最后我們看看導(dǎo)出到word的效果,如下圖:
圖七 導(dǎo)出到word效果
三、保存模版
通過(guò)上文,我們完成了自己所需的模版,然后就保存,以后可以直接使用即可,在工具欄中[Report--->Create Template From Section],然后Ctrl+S就會(huì)要求保存,取名保存即可。
public static List<String> executeQuery(String sql,String columns) {
try {
Connection conn = getConnection();
Statement st = conn.createStatement();
ResultSet set = st.executeQuery(sql);
List<String> result = new ArrayList<String>();
while (set.next()) {
String[] columnList = columns.split(",");
for(String str:columnList){
result.add(set.getString(str));
}
}
set.close();
st.close();
conn.close();
return result;
} catch (SQLException e) {
throw new IllegalArgumentException(e);
}
}
public static Connection getConnection() {
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
String url = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=jdl";
String username = "sa";
String password = "";
Connection conn = DriverManager.getConnection(url, username,
password);
return conn;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
1)、下載MongoDB
http://downloads.mongodb.org/win32/mongodb-win32-i386-2.0.4.zip
2)、設(shè)置MongoDB目錄
將其解壓到 d:\,再重命名為mongodb,路徑為d:\mongodb
3)、設(shè)置數(shù)據(jù)文件路徑
在d:盤(pán)建一個(gè)data文件夾,在data文件夾中新建db文件夾,路徑d:\data\db
4)、啟動(dòng)MongoDB服務(wù)
進(jìn)入 cmd 提示符控制臺(tái),
D:\mongodb\bin\mongod.exe --dbpath=d:\data\db
<!--[if !supportLists]-->1. <!--[endif]-->Mon Apr 16 08:50:54
<!--[if !supportLists]-->2. <!--[endif]-->Mon Apr 16 08:50:54 warning: 32-bit servers don't have journaling enabled by def
<!--[if !supportLists]-->3. <!--[endif]-->ault. Please use --journal if you want durability.
<!--[if !supportLists]-->4. <!--[endif]-->Mon Apr 16 08:50:54
<!--[if !supportLists]-->5. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] MongoDB starting : pid=5084 port=27017 dbpat
<!--[if !supportLists]-->6. <!--[endif]-->h=d:\data\db 32-bit host=PC-201012302214
<!--[if !supportLists]-->7. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten]
<!--[if !supportLists]-->8. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] ** NOTE: when using MongoDB 32 bit, you are
<!--[if !supportLists]-->9. <!--[endif]-->limited to about 2 gigabytes of data
<!--[if !supportLists]-->10. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] ** see http://blog.mongodb.org/post/13
<!--[if !supportLists]-->11. <!--[endif]-->7788967/32-bit-limitations
<!--[if !supportLists]-->12. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] ** with --journal, the limit is lower
<!--[if !supportLists]-->13. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten]
<!--[if !supportLists]-->14. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] db version v2.0.4, pdfile version 4.5
<!--[if !supportLists]-->15. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] git version: 329f3c47fe8136c03392c8f0e548506
<!--[if !supportLists]-->16. <!--[endif]-->cb21f8ebf
<!--[if !supportLists]-->17. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] build info: windows sys.getwindowsversion(ma
<!--[if !supportLists]-->18. <!--[endif]-->jor=6, minor=0, build=6002, platform=2, service_pack='Service Pack 2') BOOST_LIB
<!--[if !supportLists]-->19. <!--[endif]-->_VERSION=1_42
<!--[if !supportLists]-->20. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] options: { dbpath: "d:\data\db" }
<!--[if !supportLists]-->21. <!--[endif]-->Mon Apr 16 08:50:54 [websvr] admin web console waiting for connections on port 2
<!--[if !supportLists]-->22. <!--[endif]-->8017
<!--[if !supportLists]-->23. <!--[endif]-->Mon Apr 16 08:50:54 [initandlisten] waiting for connections on port 27017
MongoDB服務(wù)端的默認(rèn)連接端口:27017
5)、將MongoDB作為 Windows 服務(wù)隨機(jī)啟動(dòng)
先創(chuàng)建D:\mongodb\logs\mongodb.log文件,用于存儲(chǔ)MongoDB的日志文件, 再安裝系統(tǒng)服務(wù):
D:\mongodb\bin\mongod --dbpath=d:\data\db --logpath=d:\mongodb\log
s\mongodb.log --install
all output going to: d:\mongodb\logs\mongodb.log
Creating service MongoDB.
Service creation successful.
Service can be started from the command line via 'net start "MongoDB"'.
D:\>net start mongodb
Mongo DB 服務(wù)已經(jīng)啟動(dòng)成功。
D:>
注意:如果需要卸載服務(wù),執(zhí)行命令:sc delete MongoDB
6)、客戶端連接驗(yàn)證
新打開(kāi)一個(gè)CMD輸入:d:\mongodb\bin\mongo,如果出現(xiàn)下面提示,那么您就可以開(kāi)始MongoDB之旅了:
<!--[if !supportLists]-->1. <!--[endif]-->d:\mongodb\bin\mongo
<!--[if !supportLists]-->2. <!--[endif]-->MongoDB shell version: 2.0.4
<!--[if !supportLists]-->3. <!--[endif]-->connecting to: test
<!--[if !supportLists]-->4. <!--[endif]-->>
7)、查看MongoDB日志
查看D:\mongodb\logs\mongodb.log文件,即可對(duì)MongoDB的運(yùn)行情況進(jìn)行查看或排錯(cuò)。
方案一:
希望實(shí)現(xiàn) 當(dāng)鼠標(biāo)離開(kāi)一個(gè)DIV的時(shí)候觸發(fā)一個(gè)事件處理函數(shù) 于是用onmouseout 結(jié)果卻發(fā)現(xiàn)它的觸發(fā)是不是也太敏感了 原因現(xiàn)在也沒(méi)有弄清楚 IE下好像是因?yàn)閰^(qū)分mouseout時(shí)的fromElement還是toElement ,IE 5.5以上的onmouseleave事件就比較好用 偏FF又不支持這個(gè)事件 只有自己想辦法手工判斷了。
<SCRIPT> /*** * 參數(shù)e 是對(duì)象傳遞的觸發(fā)事件 FF下想訪問(wèn)event對(duì)象必須傳遞event參數(shù) * 參數(shù)o 是目標(biāo)DIV對(duì)象 */ function fun(e,o) { /* FF 下判斷鼠標(biāo)是否離開(kāi)DIV */ if(window.navigator.userAgent.indexOf("Firefox")>=1) { var x = e.clientX + document.body.scrollLeft; var y = e.clientY + document.body.scrollTop ; var left = o.offsetLeft; var top = o.offsetTop; var w = o.offsetWidth; var h = o.offsetHeight; if(y < top || y > (h + top) || x > left + w || x<left ) { alert("mouseout"); } } /* IE */ if(o.contains(event.toElement ) == false ) alert("mouseout"); } </SCRIPT> <DIV onmouseout=fun(event,this)>content</DIV> |
方案二:(與一相似)
js的onmouseout有很奇怪的一個(gè)問(wèn)題。例如
<div onmouseout="alert(123)">
<a href="#">test</a>
</div>
我們預(yù)期只有當(dāng)鼠標(biāo)從div中移開(kāi)的時(shí)候才會(huì)觸發(fā)onmouseout事件,可是,事實(shí)上,當(dāng)我們移到div中的元素時(shí),例如本例中的a標(biāo)簽時(shí),就會(huì)觸發(fā)onmousout事件。也就是說(shuō),移到對(duì)象的子對(duì)象上,也算onmouseout了。這往往會(huì)讓我們預(yù)期的效果達(dá)不到。今天的工作就遇到了這個(gè)問(wèn)題。在blueidea上搜了一下,找了解決辦法。兼容IE和FF。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿當(dāng)制作</title>
</head>
<body>
<script type="text/javascript">
function test(obj, e) {
if (e.currentTarget) {
if (e.relatedTarget != obj) {
if (obj != e.relatedTarget.parentNode) {
alert(1);
}
}
} else {
if (e.toElement != obj) {
if (obj != e.toElement.parentNode) {
alert(1);
}
}
}
}
</script>
<div onmouseout="test(this, event)" style="width:100px;height:100px;border:1px #666 solid">
<span style="margin:5px;width:100%;height:100%;border:1px #ff0000 solid">faddsf</span>
</div>
</body>
</html>
今天發(fā)現(xiàn)JQ中關(guān)于這個(gè)問(wèn)題,已經(jīng)有了一個(gè)好的解決辦法了.呵呵,jquery中定義了一種事件叫做"mouseleave",用這個(gè)事件做事件句柄的話,就可以解決這個(gè)問(wèn)題了.越來(lái)越發(fā)現(xiàn)jquery是個(gè)好東西了.
方案三:
,jQuery V1.2.2推薦用bind("mouseleave",function(){})來(lái)代替以前的mouseover方法
用bind("mouseenter",function(){})來(lái)代替mouseout,同樣也針對(duì)以前的hover方法,要看詳細(xì)的說(shuō)明點(diǎn)這個(gè)地址:http://docs.jquery.com/Release:jQuery_1.2.2
$(document).ready(function() {
$("#a1").bind("mouseleave", function(){
$('<div style="color:red;">out</div>')
.insertAfter($(this));
});
});
1. 為查詢緩存優(yōu)化你的查詢
大多數(shù)的MySQL服務(wù)器都開(kāi)啟了查詢緩存。這是提高性最有效的方法之一,而且這是被MySQL的數(shù)據(jù)庫(kù)引擎處理的。當(dāng)有很多相同的查詢被執(zhí)行了多次的時(shí)候,這些查詢結(jié)果會(huì)被放到一個(gè)緩存中,這樣,后續(xù)的相同的查詢就不用操作表而直接訪問(wèn)緩存結(jié)果了。
這里最主要的問(wèn)題是,對(duì)于程序員來(lái)說(shuō),這個(gè)事情是很容易被忽略的。因?yàn)?,我們某些查詢語(yǔ)句會(huì)讓MySQL不使用緩存。請(qǐng)看下面的示例:
1 // 查詢緩存不開(kāi)啟
2 $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()");
3
4 // 開(kāi)啟查詢緩存
5 $today = date("Y-m-d");
6 $r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
上面兩條SQL語(yǔ)句的差別就是 CURDATE() ,MySQL的查詢緩存對(duì)這個(gè)函數(shù)不起作用。所以,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數(shù)都不會(huì)開(kāi)啟查詢緩存,因?yàn)檫@些函數(shù)的返回是會(huì)不定的易變的。所以,你所需要的就是用一個(gè)變量來(lái)代替MySQL的函數(shù),從而開(kāi)啟緩存。
2. 當(dāng)只要一行數(shù)據(jù)時(shí)使用 LIMIT 1
當(dāng)你查詢表的有些時(shí)候,你已經(jīng)知道結(jié)果只會(huì)有一條結(jié)果,但因?yàn)槟憧赡苄枰?/span>fetch游標(biāo),或是你也許會(huì)去檢查返回的記錄數(shù)。
在這種情況下,加上 LIMIT 1 可以增加性能。這樣一樣,MySQL數(shù)據(jù)庫(kù)引擎會(huì)在找到一條數(shù)據(jù)后停止搜索,而不是繼續(xù)往后查少下一條符合記錄的數(shù)據(jù)。
下面的示例,只是為了找一下是否有“中國(guó)”的用戶,很明顯,后面的會(huì)比前面的更有效率。(請(qǐng)注意,第一條中是Select *,第二條是Select 1)
01 // 沒(méi)有效率的:
02 $r = mysql_query("SELECT * FROM user WHERE country = 'China'");
03 if (mysql_num_rows($r) > 0) {
04 // ...
05 }
06
07 // 有效率的:
08 $r = mysql_query("SELECT 1 FROM user WHERE country = 'China' LIMIT 1");
09 if (mysql_num_rows($r) > 0) {
10 // ...
11 }
3. 千萬(wàn)不要 ORDER BY RAND()
想打亂返回的數(shù)據(jù)行?隨機(jī)挑一個(gè)數(shù)據(jù)?真不知道誰(shuí)發(fā)明了這種用法,但很多新手很喜歡這樣用。但你確不了解這樣做有多么可怕的性能問(wèn)題。
如果你真的想把返回的數(shù)據(jù)行打亂了,你有N種方法可以達(dá)到這個(gè)目的。這樣使用只讓你的數(shù)據(jù)庫(kù)的性能呈指數(shù)級(jí)的下降。這里的問(wèn)題是:MySQL會(huì)不得不去執(zhí)行RAND()函數(shù)(很耗CPU時(shí)間),而且這是為了每一行記錄去記行,然后再對(duì)其排序。就算是你用了Limit 1也無(wú)濟(jì)于事(因?yàn)橐判颍?/span>
下面的示例是隨機(jī)挑一條記錄
1 // 千萬(wàn)不要這樣做:
2 $r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1");
3
4 // 這要會(huì)更好:
5 $r = mysql_query("SELECT count(*) FROM user");
6 $d = mysql_fetch_row($r);
7 $rand = mt_rand(0,$d[0] - 1);
8
9 $r = mysql_query("SELECT username FROM user LIMIT $rand, 1");
4. 避免 SELECT *
從數(shù)據(jù)庫(kù)里讀出越多的數(shù)據(jù),那么查詢就會(huì)變得越慢。并且,如果你的數(shù)據(jù)庫(kù)服務(wù)器和WEB服務(wù)器是兩臺(tái)獨(dú)立的服務(wù)器的話,這還會(huì)增加網(wǎng)絡(luò)傳輸?shù)呢?fù)載。
所以,你應(yīng)該養(yǎng)成一個(gè)需要什么就取什么的好的習(xí)慣。
1 // 不推薦
2 $r = mysql_query("SELECT * FROM user WHERE user_id = 1");
3 $d = mysql_fetch_assoc($r);
4 echo "Welcome {$d['username']}";
5
6 // 推薦
7 $r = mysql_query("SELECT username FROM user WHERE user_id = 1");
8 $d = mysql_fetch_assoc($r);
9 echo "Welcome {$d['username']}";
5. 永遠(yuǎn)為每張表設(shè)置一個(gè)ID
我們應(yīng)該為數(shù)據(jù)庫(kù)里的每張表都設(shè)置一個(gè)ID做為其主鍵,而且最好的是一個(gè)INT型的(推薦使用UNSIGNED),并設(shè)置上自動(dòng)增加的AUTO_INCREMENT標(biāo)志。
就算是你 users 表有一個(gè)主鍵叫 “email”的字段,你也別讓它成為主鍵。使用 VARCHAR 類型來(lái)當(dāng)主鍵會(huì)使用得性能下降。另外,在你的程序中,你應(yīng)該使用表的ID來(lái)構(gòu)造你的數(shù)據(jù)結(jié)構(gòu)。
而且,在MySQL數(shù)據(jù)引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設(shè)置變得非常重要,比如,集群,分區(qū)……
在這里,只有一個(gè)情況是例外,那就是“關(guān)聯(lián)表”的“外鍵”,也就是說(shuō),這個(gè)表的主鍵,通過(guò)若干個(gè)別的表的主鍵構(gòu)成。我們把這個(gè)情況叫做“外鍵”。比如:有一個(gè)“學(xué)生表”有學(xué)生的ID,有一個(gè)“課程表”有課程ID,那么,“成績(jī)表”就是“關(guān)聯(lián)表”了,其關(guān)聯(lián)了學(xué)生表和課程表,在成績(jī)表中,學(xué)生ID和課程ID叫“外鍵”其共同組成主鍵。
6. 使用 ENUM 而不是 VARCHAR
ENUM 類型是非??旌途o湊的。在實(shí)際上,其保存的是 TINYINT,但其外表上顯示為字符串。這樣一來(lái),用這個(gè)字段來(lái)做一些選項(xiàng)列表變得相當(dāng)?shù)耐昝馈?/span>
如果你有一個(gè)字段,比如“性別”,“國(guó)家”,“民族”,“狀態(tài)”或“部門(mén)”,你知道這些字段的取值是有限而且固定的,那么,你應(yīng)該使用 ENUM 而不是 VARCHAR。
MySQL也有一個(gè)“建議”(見(jiàn)第十條)告訴你怎么去重新組織你的表結(jié)構(gòu)。當(dāng)你有一個(gè) VARCHAR 字段時(shí),這個(gè)建議會(huì)告訴你把其改成 ENUM 類型。使用 PROCEDURE ANALYSE() 你可以得到相關(guān)的建議。
除非你有一個(gè)很特別的原因去使用 NULL 值,你應(yīng)該總是讓你的字段保持 NOT NULL。這看起來(lái)好像有點(diǎn)爭(zhēng)議,請(qǐng)往下看。
首先,問(wèn)問(wèn)你自己“Empty”和“NULL”有多大的區(qū)別(如果是INT,那就是0和NULL)?如果你覺(jué)得它們之間沒(méi)有什么區(qū)別,那么你就不要使用NULL。(你知道嗎?在 Oracle 里,NULL 和 Empty 的字符串是一樣的!)
不要以為 NULL 不需要空間,其需要額外的空間,并且,在你進(jìn)行比較的時(shí)候,你的程序會(huì)更復(fù)雜。當(dāng)然,這里并不是說(shuō)你就不能使用NULL了,現(xiàn)實(shí)情況是很復(fù)雜的,依然會(huì)有些情況下,你需要使用NULL值。
很多程序員都會(huì)創(chuàng)建一個(gè) VARCHAR(15) 字段來(lái)存放字符串形式的IP而不是整形的IP。如果你用整形來(lái)存放,只需要4個(gè)字節(jié),并且你可以有定長(zhǎng)的字段。而且,這會(huì)為你帶來(lái)查詢上的優(yōu)勢(shì),尤其是當(dāng)你需要使用這樣的WHERE條件:IP between ip1 and ip2。
我們必需要使用UNSIGNED INT,因?yàn)?IP地址會(huì)使用整個(gè)32位的無(wú)符號(hào)整形。
而你的查詢,你可以使用 INET_ATON() 來(lái)把一個(gè)字符串IP轉(zhuǎn)成一個(gè)整形,并使用 INET_NTOA() 把一個(gè)整形轉(zhuǎn)成一個(gè)字符串IP
如果你需要在一個(gè)在線的網(wǎng)站上去執(zhí)行一個(gè)大的 DELETE 或 INSERT 查詢,你需要非常小心,要避免你的操作讓你的整個(gè)網(wǎng)站停止相應(yīng)。因?yàn)檫@兩個(gè)操作是會(huì)鎖表的,表一鎖住了,別的操作都進(jìn)不來(lái)了。
如果你把你的表鎖上一段時(shí)間,比如30秒鐘,那么對(duì)于一個(gè)有很高訪問(wèn)量的站點(diǎn)來(lái)說(shuō),這30秒所積累的訪問(wèn)進(jìn)程/線程,數(shù)據(jù)庫(kù)鏈接,打開(kāi)的文件數(shù),可能不僅僅會(huì)讓你泊WEB服務(wù)Crash,還可能會(huì)讓你的整臺(tái)服務(wù)器馬上宕機(jī)。
所以,如果你有一個(gè)大的處理,你定你一定把其拆分,使用 LIMIT 條件是一個(gè)好的方法。下面是一個(gè)示例:
01 while (1) {
02 //每次只做1000條
03 mysql_query("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");
04 if (mysql_affected_rows() == 0) {
05 // 沒(méi)得可刪了,退出!
06 break;
07 }
08 // 每次都要休息一會(huì)兒
09 usleep(50000);
10 }
對(duì)于大多數(shù)的數(shù)據(jù)庫(kù)引擎來(lái)說(shuō),硬盤(pán)操作可能是最重大的瓶頸。所以,把你的數(shù)據(jù)變得緊湊會(huì)對(duì)這種情況非常有幫助,因?yàn)檫@減少了對(duì)硬盤(pán)的訪問(wèn)。
如果一個(gè)表只會(huì)有幾列罷了(比如說(shuō)字典表,配置表),那么,我們就沒(méi)有理由使用 INT 來(lái)做主鍵,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 會(huì)更經(jīng)濟(jì)一些。
首先看一下分頁(yè)的基本原理:
mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20\G
***************** 1. row **************
id: 1
select_type: SIMPLE
table: message
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 10020
Extra:
1 row in set (0.00 sec)
limit 10000,20的意思掃描滿足條件的10020行,扔掉前面的10000行,返回最后的20行,問(wèn)題就在這里,如果是limit 100000,100,需要掃描100100行,在一個(gè)高并發(fā)的應(yīng)用里,每次查詢需要掃描超過(guò)10W行,性能肯定大打折扣。
一種”clue”的做法,給翻頁(yè)提供一些”線索”,比如還是SELECT * FROM message ORDER BY id DESC,按id降序分頁(yè),每頁(yè)20條,當(dāng)前是第10頁(yè),當(dāng)前頁(yè)條目id最大的是9527,最小的是9500,如果我們只提供”上一頁(yè)”、”下一頁(yè)”這樣的跳轉(zhuǎn)(不提供到第N頁(yè)的跳轉(zhuǎn)),那么在處理”上一頁(yè)”的時(shí)候SQL語(yǔ)句可以是:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20;
處理”下一頁(yè)”的時(shí)候SQL語(yǔ)句可以是:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 20;
不管翻多少頁(yè),每次查詢只掃描20行。
缺點(diǎn)是只能提供”上一頁(yè)”、”下一頁(yè)”的鏈接形式,但是有些人非常喜歡”<上一頁(yè) 1 2 3 4 5 6 7 8 9 下一頁(yè)>”這樣的鏈接方式,怎么辦呢?
如果LIMIT m,n不可避免的話,要優(yōu)化效率,只有盡可能的讓m小一下,我們擴(kuò)展前面的”clue”做法,還是SELECT * FROM message ORDER BY id DESC,按id降序分頁(yè),每頁(yè)20條,當(dāng)前是第10頁(yè),當(dāng)前頁(yè)條目id最大的是9527,最小的是9500,比如要跳到第8頁(yè),我看的SQL語(yǔ)句可以這樣寫(xiě):
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20,20;
跳轉(zhuǎn)到第13頁(yè):
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 40,20;
原理還是一樣,記錄住當(dāng)前頁(yè)id的最大值和最小值,計(jì)算跳轉(zhuǎn)頁(yè)面和當(dāng)前頁(yè)相對(duì)偏移,由于頁(yè)面相近,這個(gè)偏移量不會(huì)很大,這樣的話m值相對(duì)較小,大大減少掃描的行數(shù)。其實(shí)傳統(tǒng)的limit m,n,相對(duì)的偏移一直是第一頁(yè),這樣的話越翻到后面,效率越差,而上面給出的方法就沒(méi)有這樣的問(wèn)題。
1.1何為maven坐標(biāo)
Mavne的一大功能是管理項(xiàng)目依賴,為了能自動(dòng)化的解析任何一個(gè)Java構(gòu)件,maven就必須將它們唯一標(biāo)識(shí),這就依賴管理的底層基礎(chǔ)—-坐標(biāo)。
Maven的世界中擁有數(shù)量非常巨大的構(gòu)件,也就是平時(shí)用的一些jar、war等文件,在Maven為這些構(gòu)件引入坐標(biāo)概念之前,我們無(wú)法使用任何一種方式來(lái)唯一標(biāo)識(shí)所有這些構(gòu)件。因此maven定義了這樣組規(guī)則:世界上任何一個(gè)構(gòu)件都可以使用Maven坐標(biāo)唯一標(biāo)識(shí),maven坐標(biāo)元素包括groupId、artifactId、version、packaging、classifier?,F(xiàn)在,只要我們提供正確的坐標(biāo)元素,maven就能找到對(duì)應(yīng)的組件。比如說(shuō),當(dāng)需要使用Java5平臺(tái)上TestNG的5.8版本時(shí),就告訴Maven:“groupId=org.testng;artifactId=testng;version=5.9;classifier=jdk15
”,maven就會(huì)從倉(cāng)庫(kù)中尋找相應(yīng)的構(gòu)件供我們使用。Maven是從哪里下載構(gòu)件的呢?maven內(nèi)置了一個(gè)中央倉(cāng)庫(kù)的地址(http://repol.maven.org/maven2),該中央倉(cāng)庫(kù)包含了世界上大部分流行的開(kāi)源項(xiàng)目組件,maven會(huì)在需要的時(shí)候去那里下載。
1.2坐標(biāo)詳解
先看一組坐標(biāo)定義,如下:
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
這是nexus-indexer的坐標(biāo)定義,nexus-indexer是一個(gè)對(duì)maven倉(cāng)庫(kù)編纂索引并提供搜索功能的類庫(kù),它是Nexus項(xiàng)目的一個(gè)子模塊。下面解釋一下各個(gè)坐標(biāo)元素:
上述五個(gè)元素中,groupId、artifactId、version是必須定義的,packaging是可選的(默認(rèn)為jar),而classifier是不能直接定義的。
理解清楚Maven坐標(biāo)之后,我們就能開(kāi)始討論Maven的依賴管理了。
1.3依賴的配置
一個(gè)依賴聲明可以包含如下的一些元素:
<project>
…
<dependencies>
<dependency>
<groupId>…</groupId>
<artifactId>…</artifactId>
<version>…</version>
<type>…</type>
<scope>…</scope>
<optional>…</optional>
<exclusions>
<exclusion>
…
</exclusion>
…
</exclusions>
</dependency>
…
</dependencies>
…
</project>
Dependencies可以包含一個(gè)或者多個(gè)dependency元素,以聲明一個(gè)或者多個(gè)項(xiàng)目依賴。每個(gè)依賴可以包含的元素有:
1.4依賴范圍
首先需要知道,Maven在編譯項(xiàng)目主代碼的時(shí)候需要使用一套classpath。其次,Maven在編譯和執(zhí)行測(cè)試的時(shí)候會(huì)使用另外一套classpath。最后,實(shí)際運(yùn)行Maven項(xiàng)目的時(shí)候,又會(huì)使用一套classpath。
依賴范圍就是用來(lái)控制依賴與這三種classpath(編譯classpaht、測(cè)試classpath、運(yùn)行classpath)的關(guān)系,Maven有以下幾種依賴范圍:
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/tr.jar</systemPath>
</dependency>
1.5傳遞性依賴
何為傳遞性依賴?現(xiàn)在舉一個(gè)例子:項(xiàng)目中有一個(gè)compile范圍的spring-core依賴,spring-core有一個(gè)compile范圍的commons-logging依賴,那么commons-logging就會(huì)成為該項(xiàng)目的compile范圍依賴,commons-logging是該項(xiàng)目的一個(gè)傳遞依賴。
Maven會(huì)解析各個(gè)直接依賴的POM,將那些必要的間接依賴以傳遞性依賴的形式引入到當(dāng)前項(xiàng)目中。
依賴范圍不僅可以控制依賴與三種classpath的關(guān)系,還對(duì)傳遞性依賴產(chǎn)生影響。假設(shè)A依賴于B,B依賴于C,我們說(shuō)A對(duì)于B是第一直接依賴,B對(duì)于C是第二直接依賴,A對(duì)于C是傳遞性依賴。第一直接依賴的范圍和第二直接依賴的范圍決定了傳遞性依賴的范圍,如表,最左邊一列表示第一直接依賴范圍,最上面一行表示第二直接依賴范圍,中間的交叉單元格則表示傳遞性依賴范圍
compile |
test |
provided |
runtime | |
compile |
compile |
—— |
—— |
runtime |
test |
test |
—— |
—— |
test |
provided |
provided |
—— |
provided |
provided |
runtime |
runtime |
—— |
—— |
runtime |
仔細(xì)觀察一下表可以發(fā)現(xiàn)這樣的規(guī)律:當(dāng)?shù)诙苯右蕾嚨姆秶莄ompile的時(shí)候,傳遞性依賴的范圍與第一直接依賴的范圍一致;當(dāng)?shù)诙苯右蕾嚨姆秶莟est的時(shí)候,依賴不會(huì)得以傳遞;當(dāng)?shù)诙苯右蕾嚨姆秶鸀閜rovided的時(shí)候,只傳遞第一直接依賴的范圍為provided的依賴,且傳遞性依賴的范圍同樣為provided;當(dāng)?shù)诙苯右蕾嚨姆秶莚untime的時(shí)候,傳遞性依賴的范圍與第一直接依賴的范圍一致,但compile除外,此時(shí)傳遞性依賴的范圍為runtime。
1.6依賴調(diào)解
Maven引入的傳遞性依賴機(jī)制,一方面大大簡(jiǎn)化和方便了依賴聲明,另一方面,大部分情況下我們只需要關(guān)心項(xiàng)目的直接依賴是什么,而不用考慮這些直接依賴會(huì)引入什么傳遞依賴。但是有時(shí)候,當(dāng)傳遞性依賴造成問(wèn)題的時(shí)候,我們就需要清楚的知道該傳遞性依賴是從哪條依賴路徑引入的。
例如A->B->C->X(1.0)、A->D->X(2.0),X是A的傳遞性依賴,但是兩條依賴路徑上有兩個(gè)版本的X,那個(gè)X會(huì)被Maven解析使用呢?Maven依賴調(diào)解的第一原則是:路徑最近者優(yōu)先。依賴調(diào)解第一原則不能解決所有問(wèn)題,比如:A->B->Y(1.0)、A->C->Y(2.0),Y(1.0)和Y(2.0)的依賴路徑長(zhǎng)度是一樣的,到底誰(shuí)會(huì)解析?在Maven2.0.9開(kāi)始,Maven定義了依賴調(diào)解的第二原則:第一聲明者優(yōu)先。
官網(wǎng)的API:http://api.jquery.com/
需要的JS文件:jquery.tmpl.min.js
Tmpl提供了幾種tag:
jquery tmpl的使用方法:
模板定義:
方法一:<
script
id
=
"movieTemplate"
type
=
"text/x-jquery-tmpl"
>
<
li
>
<
b
>${Name}</
b
> (${ReleaseYear})
</
li
>
</
script
>
方法二:
function makeTemplate(){
<
li
>
<
b
>${Name}</
b
> (${ReleaseYear})
</
li
>
‘;}
var
movies = [
{ Name:
"The Red Violin"
, ReleaseYear:
"1998"
},
{ Name:
"Eyes Wide Shut"
, ReleaseYear:
"1999"
},
{ Name:
"The Inheritance"
, ReleaseYear:
"1976"
}
];
$(
"#movieTemplate"
).tmpl( movies )
.appendTo(
"#movieList"
);