The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

#

I’ve been tweaking the performance of BlogEngine.NEXT today using my favorite tool: YSlow for FireBug. One of the things YSlow checks for is the expires HTTP header for static content such as images, script files and style sheets. Since BlogEngine.NET has always used custom HTTP handlers for serving scripts and stylesheets, only the static images have been a problem.

The problem

The problem is that with images on hosted environments on IIS 6, it’s impossible to control the serving of them without redirecting them through an HTTP handler. That’s not a good idea for several reasons:

  • It adds unnecessary overhead by going through the ASP.NET ISAPI
  • You need to add custom code to handle the requests
  • You need to change the URL from .gif to .gif.axd or similar

Here is what YSlow finds on my website that needs the expires header set to a far future date:


As you can see, it is all my static images that lacks the expires header.

The solution

If you run IIS 6 there is no good way of adding an expires header to images unless you have control over the IIS. If your site is hosted then you probably have no control at all. If you are using IIS 7 however, you can very easily add the header in your web.config’s system.webServer section like so:

<staticContent>
 <clientCache httpExpires="Sun, 29 Mar 2020 00:00:00 GMT" cacheControlMode="UseExpires" />
</staticContent>

What happens is that all static content will now have an expires HTTP header set to the year 2020. Static content means anything that isn’t served through the ASP.NET engine such as images, script files and styles sheets. This is one of the very easy tricks that will increase the performance of your site as well as your YSlow score.

posted @ 2010-07-21 10:23 Eric_jiang 阅读(1159) | 评论 (0)编辑 收藏



Div即父容器不根据内容自适应高度,我们看下面的代码:
<div id="main">
<div id="content"></div>
</div>
当Content内容多时,即使main设置了高度100%或auto。在不同浏览器下还是不能完好的自动伸展。内容的高度比较高了,但容器main的高度还是不能撑开。

我们可以通过三种方法来解决这个问题。 
1增加一个清除浮动,让父容器知道高度。请注意,清除浮动的容器中有一个空格。
<div id="main">
<div id="content"></div>
<div style="font: 0px/0px sans-serif;clear: both;display: block"> </div>
</div>

2增加一个容器,在代码中存在,但在视觉中不可见。
<div id="main">
<div id="content"></div>
<div style="height:1px; margin-top:-1px;clear: both;overflow:hidden;"></div>
</div>

3增加一个BR并设置样式为clear:both。
<div id="main">
<div id="content"></div>
<br style="clear:both;" />
</div>

补充:
<div id="main">
<div id="content">
  <p>demo1</p>
  <p>demo2</p>
  <p>demo3</p>
</div>
</div>
#main { border:1px solid #999999; background-color:#CCCCCC; height:100%; overflow:hidden;}
#content { float:left;}

以上三个方法都不是最好的解决方法,因为在程序代码观念中是提倡尽量不要添加无意义的标签代码

介绍我的解决方法是直接在最外层div加以下样式
#main {
height:100%;
overflow:hidden;
}
posted @ 2010-07-20 10:14 Eric_jiang 阅读(421) | 评论 (1)编辑 收藏

     摘要: 1、页面代码 Html代码 <%@ page contentType="text/html;charset=UTF-8"%>   <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> ...  阅读全文
posted @ 2010-07-14 21:26 Eric_jiang 阅读(1770) | 评论 (0)编辑 收藏

  1. import java.awt.AlphaComposite;      
  2. import java.awt.Color;      
  3. import java.awt.Font;      
  4. import java.awt.Graphics2D;      
  5. import java.awt.Image;      
  6. import java.awt.geom.AffineTransform;      
  7. import java.awt.image.AffineTransformOp;      
  8. import java.awt.image.BufferedImage;      
  9. import java.io.File;      
  10. import java.io.IOException;      
  11.      
  12. import javax.imageio.ImageIO;      
  13.      
  14.      
  15. public final class ImageUtils {      
  16.     /**    
  17.      * 图片水印    
  18.      *     
  19.      * @param pressImg    
  20.      *            水印图片    
  21.      * @param targetImg    
  22.      *            目标图片    
  23.      * @param x    
  24.      *            修正值 默认在中 间    
  25.      * @param y    
  26.      *            修正值 默认在中 间    
  27.      * @param alpha    
  28.      *            透明度    
  29.      */     
  30.     public final static void pressImage(String pressImg, String targetImg, int x, int y, float alpha) {      
  31.         try {      
  32.             File img = new File(targetImg);      
  33.             Image src = ImageIO.read(img);      
  34.             int wideth = src.getWidth(null);      
  35.             int height = src.getHeight(null);      
  36.             BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);      
  37.             Graphics2D g = image.createGraphics();      
  38.             g.drawImage(src, 0, 0, wideth, height, null);      
  39.             // 水印 文件      
  40.             Image src_biao = ImageIO.read(new File(pressImg));      
  41.             int wideth_biao = src_biao.getWidth(null);      
  42.             int height_biao = src_biao.getHeight(null);      
  43.             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));      
  44.             g.drawImage(src_biao, (wideth - wideth_biao) / 2, (height - height_biao) / 2, wideth_biao, height_biao, null);      
  45.             // 水印 文件结束      
  46.             g.dispose();      
  47.             ImageIO.write((BufferedImage) image, "jpg", img);      
  48.         } catch (Exception e) {      
  49.             e.printStackTrace();      
  50.         }      
  51.     }      
  52.      
  53.     /**    
  54.      * 文字水印    
  55.      *     
  56.      * @param pressText    
  57.      *            水印文字    
  58.      * @param targetImg    
  59.      *            目标图片    
  60.      * @param fontName    
  61.      *            字体名称    
  62.      * @param fontStyle    
  63.      *            字体样式    
  64.      * @param color    
  65.      *            字体颜色    
  66.      * @param fontSize    
  67.      *            字体大小    
  68.      * @param x    
  69.      *            修正值    
  70.      * @param y    
  71.      *            修正值    
  72.      * @param alpha    
  73.      *            透明度    
  74.      */     
  75.     public static void pressText(String pressText, String targetImg, String fontName, int fontStyle, Color color, int fontSize, int x, int y, float alpha) {      
  76.         try {      
  77.             File img = new File(targetImg);      
  78.             Image src = ImageIO.read(img);      
  79.             int width = src.getWidth(null);      
  80.             int height = src.getHeight(null);      
  81.             BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);      
  82.             Graphics2D g = image.createGraphics();      
  83.             g.drawImage(src, 0, 0, width, height, null);      
  84.             g.setColor(color);      
  85.             g.setFont(new Font(fontName, fontStyle, fontSize));      
  86.             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));      
  87.             g.drawString(pressText, (width - (getLength(pressText) * fontSize)) / 2 + x, (height - fontSize) / 2 + y);      
  88.             g.dispose();      
  89.             ImageIO.write((BufferedImage) image, "jpg", img);      
  90.         } catch (Exception e) {      
  91.             e.printStackTrace();      
  92.         }      
  93.     }      
  94.      
  95.     /**    
  96.      * 缩放    
  97.      *     
  98.      * @param filePath    
  99.      *            图片路径    
  100.      * @param height    
  101.      *            高度    
  102.      * @param width    
  103.      *            宽度    
  104.      * @param bb    
  105.      *            比例不对时是 否需要补白    
  106.      */     
  107.     public static void resize(String filePath, int height, int width, boolean bb) {      
  108.         try {      
  109.             double ratio = 0; // 缩放比例      
  110.             File f = new File(filePath);      
  111.             BufferedImage bi = ImageIO.read(f);      
  112.             Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);      
  113.             // 计算 比例      
  114.             if ((bi.getHeight() > height) || (bi.getWidth() > width)) {      
  115.                 if (bi.getHeight() > bi.getWidth()) {      
  116.                     ratio = (new Integer(height)).doubleValue() / bi.getHeight();      
  117.                 } else {      
  118.                     ratio = (new Integer(width)).doubleValue() / bi.getWidth();      
  119.                 }      
  120.                 AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);      
  121.                 itemp = op.filter(bi, null);      
  122.             }      
  123.             if (bb) {      
  124.                 BufferedImage image = new BufferedImage(width, height,      
  125.                         BufferedImage.TYPE_INT_RGB);      
  126.                 Graphics2D g = image.createGraphics();      
  127.                 g.setColor(Color.white);      
  128.                 g.fillRect(0, 0, width, height);      
  129.                 if (width == itemp.getWidth(null))      
  130.                     g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null), itemp.getHeight(null), Color.white, null);      
  131.                 else     
  132.                     g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null), itemp.getHeight(null), Color.white, null);      
  133.                 g.dispose();      
  134.                 itemp = image;      
  135.             }      
  136.             ImageIO.write((BufferedImage) itemp, "jpg", f);      
  137.         } catch (IOException e) {      
  138.             e.printStackTrace();      
  139.         }      
  140.     }      
  141.      
  142.     public static void main(String[] args) throws IOException {      
  143.         pressImage("G:""imgtest""sy.jpg", "G:""imgtest""testjpg", 0, 0, 5f);      
  144.         pressText("我是 文字水印", "G:""imgtest""testjpg", "黑体", 36, Color.white, 80,      
  145.                 0, 0, 3f);      
  146.         resize("G:""imgtest""testjpg", 500, 500, true);      
  147.     }      
  148.      
  149.     public static int getLength(String text) {      
  150.         int length = 0;      
  151.         for (int i = 0; i < text.length(); i++) {      
  152.             if (new String(text.charAt(i) + "").getBytes().length > 1) {      
  153.                 length += 2;      
  154.             } else {      
  155.                 length += 1;      
  156.             }      
  157.         }      
  158.         return length / 2;      
  159.     }      
  160. }     
  161.  
posted @ 2010-07-14 20:04 Eric_jiang 阅读(270) | 评论 (0)编辑 收藏

很早之前就听说有jslint这个东东,但是一直没有用过。说得简单点,这是一个js代码校验的工具。

官方网站:http://www.jslint.com/lint.html

在线校验地址:http://www.jslint.com/

用在线校验的校验有些不太方便,因为每次都要粘贴复制代码。如果能把jslint结合到EditPlus里面应该灰常方便。

找到如下解决方案

http://www.jslint.com/fulljslint.js下载这个js文件,放到editplus的安装目录中,我的是C:"Program Files"EditPlus 3

菜单文本:javascript调试
调试命令:cmd /c
参数:cscript “$(FileName)” cscript “jslint的路径” < "$(FileName)"(被删除的部分是网上大部分的说法,但是我实际操作了一下,发现这段命令只会检测jslint这个文件,于是我尝试删除了<前面的东东,发现就能校验当前文件了)
初始目录:$(FileDir)
钩选:捕捉输出
在输出模式使用正则表达式:^Lint at line ([0-9]+) character ([0-9]+).*$”
上面这行好像就是默认的,不用改。


EditPlus里面配置jslint

存在问题:目前校验下来,一般的js代码如果有问题,会正常报错。但是对于我们的框架而言,只要检测到$符号,就会报错。
我想这个应该在jslint.js文件中处理一下对应的逻辑。

posted @ 2010-07-14 15:52 Eric_jiang 阅读(992) | 评论 (0)编辑 收藏

win7比以往任何一个操作系统占用内存多,系统启动的时候自带了很多系统服务,但多数系统服务我们是用不上的,完全可以关闭这些服务来节省系统资源,下面列出win7下可以关闭的系统服务,大家可以根据的实际使用情况来选择关闭哪些不用的服务。

Adaptive brightness
监视周围的光线状况来调节屏幕明暗,普通用户没有触摸屏类的显示,该功能就可以放心禁用。
Application Layer Gateway Service
Windows XP/Vista中也有该服务,作用也差不多,是系统自带防火墙和开启ICS共享上网的依赖服务,如果装有第三方防火墙且不需要用ICS方式共享上网,完全可以禁用掉。
Application Management
该服务默认的运行方式为手动,该功能主要适用于大型企业环境下的集中管理,因此家庭用户可以放心禁用该服务。
Background Intelligent Transfer Service
在后台传输客户端和服务器之间的数据。如果禁用了BITS,一些功能,如 Windows Update,就无法正常运行。该服务的默认运行方式是自动,这个服务的主要用途还是用于进行Windows Update或者自动更新,最好不要更改这个服务。
Base Filtering Engine
同样为系统防火墙,VPN以及IPsec提供依赖服务,同时也是系统安全方面的服务,如果使用第三方VPN拨号软件并且不用系统的防火墙以及ICS共享上网,为了系统资源,关闭它吧,否则就别动它。
BitLocker Drive Encryption Service
向用户接口提供BitLocker客户端服务并且自动对数据卷解锁。该服务的默认运行方式是手动,如果你没有使用BitLocker设备,该功能就可以放心禁用。
Block Level Backup Engine Service
估计是和备份恢复方面用的服务,无任何依赖关系,默认是手动,也从来没有看他启动过。就放那吧,不用管了。
Bluetooth Support Service
如果你没有使用蓝牙设备,该功能就可以放心禁用。
Certificate Propagation
为智能卡提供证书。该服务的默认运行方式是手动。如果你没有使用智能卡,那么可以放心禁用该服务。
CNG Key Isolation
那么这个服务将被使用,建议不使用自动有线网络配置和无线网络的可以关掉。
Computer Browser
不过如果你没有使用局域网或者你根本就不想使用局域网,该功能就可以放心禁用,禁用后任然可以使用
Diagnostic Policy Service
Diagnostic Policy服务为Windows组件提供诊断支持。如果该服务停止了,系统诊断工具将无法正常运行。如果该服务被禁用了,那么任何依赖该服务的其他服务都将无法正常运行。该服务的默认运行方式是自动,Vista或IE7有时会弹出对话框问你是否需要让它帮忙找到故障的原因,只有1%的情况下它会帮忙修复Internet断线的问题,可以关掉。
Diagnostic Service Host
这就是帮上面Diagnostic Policy Service做具体事情的服务,会随着上面的服务启动,可以一起关掉。
Diagnostic System Host
基本和Diagnostic Policy Service/Diagnostic Service Host是同类,可以一起关掉。
Distributed Link Tracking Client:
这个功能一般都用不上,完全可以放心禁用。

Distributed Transaction Coordinator
很多应用以及SQL,Exchange Biztalk等服务器软件都依赖这个服务,可以不启动它,但不要Disabled 它。
Extensible Authentication Protocol
不用802.1x认证、无线网络或VPN 可以不启动它,不要Disabled 它。
Fax
利用计算机或网络上的可用传真资源发送和接收传真。不用我说了吧,很明显就能看出来是和传真有关的。手动或禁用
Function Discovery Provider Host
功能发现提供程序的主机进程。PnP-X和SSDP相关,如果无相关设备就关了吧。
Function Discovery Resource Publication
PnP-X和SSDP相关,如果无相关设备就关了吧。
HomeGroup Listener
为家庭群组提供接收服务,该服务的默认运行方式是手动,如果你不使用家庭群组来共享图片视频及文档,那么该服务可以禁用。
HomeGroup Provider
为家庭群组提供网络服务,该服务的默认运行方式是自动,如果你不使用家庭群组来共享图片视频及文档,那么该服务可以禁用。
Human Interface Device Access
如果你不想你机器或笔记本键盘上面的那些特别的附加按键起作用、不用游戏手柄之类可以关掉这个服务。
IKE and AuthIP IPsec Keying Modules
不用VPN或用第三方VPN拨号的话可以禁用。
Internet Connection Sharing (ICS)
如果你不打算让这台计算机充当ICS主机,那么该服务可以禁用,否则需要启用。
IP Helper
说白了就是让IPv4和IPv6相互兼容,现在的情况下不是特别需要,其实设置成Disabled 也无妨。
IPsec Policy Agent
某些公司的网络环境要求必须打开,它提供一个TCP/IP网络上客户端和服务器之间端到端的安全连接。其他的情况建议设置成禁用。
KtmRm for Distributed Transaction Coordinator
对开发人员来说是比较有用,对于一般的用户或者非开发人员来说,设置成手动。
Link-Layer Topology Discovery Mapper
应该是支持LLTD (Link Layer Topology Discovery) 技术,可以精确地显示支持LLTD的设备在网络结构中的位置,比如Vista的无线地图 ,保持默认手动。
Microsoft iSCSI Initiator Service
如果本机没有iSCSI设备也不需要连接和访问远程iSCSI设备,设置成禁用。
Microsoft Software Shadow Copy Provider
卷影拷贝,如果不需要就可以设为禁用。
Net.Tcp 端口共享服务
一般用户和非开发人员,还是Disabled就行了。
Netlogon
登陆域会用到它。工作组环境可以设为禁用。
Offline Files
脱机文件服务,使用这个功能系统会将网络上的共享内容在本地进行缓存,可以关掉。
Parental Controls
父母控制服务,用于IE上网设置里的,如果是自己用电脑,就关掉它。
Peer Name Resolution Protocol/ Peer Networking Grouping / Peer Networking Identity Manager
如果你不尝试WCF的P2P功能或开发,那么连同相关的两个服务都可以关掉。
PnP-X IP Bus Enumerator
目前还用不上,关了它!
PNRP Machine Name Publication Service
一般不需要它。默认即可。
Portable Device Enumerator Service
用来让Windows Media Player和移动媒体播放器比如MP3进行数据和时钟同步。如不需要同步建议关闭。
Print Spooler
将文件加载到内存供稍后打印。打印服务,不用多说了,有(包括虚拟的)就开,没有就关。
Problem Reports and Solutions Control Panel Support
开了它基本也解决不了你计算机出的问题。禁用吧。
Program Compatibility Assistant Service
如果你使用到Program Compatibility Assistant或者需要将你的程序设置成兼容模式运行,比如运行在Win98 或 Windows 2000的方式下,就修改成自动,强烈建议设置为自动,如果没有这样的程序,就关掉它。
Quality Windows Audio Video Experience
个人感觉这个不起什么作用,支持这样技术的网络服务也不多。还是系统资源比较重要,关了它。
Remote Desktop Configuration/ Remote Desktop Services/ Remote Desktop Services UserMode Port Redirector
系统自带的远程桌面服务,如果不用它,就连同和它相关的两个服务一起关掉
Remote Registry
家庭个人用户最好禁用此服务,公司管理就需要打开了。
Routing and Remote Access
在局域网以及广域网环境中为企业提供路由服务。提供路由服务的。不用就关。
Secondary Logon
允许一台机器同时有两个用户登录,个人应用基本不需要。
Security Center
监视系统安全设置和配置。不想听它提示,就关上它。

Server
如果不需要在网络上共享什么东西就可以关掉。
Shell
Hardware Detection
如果你不喜欢自动播放功能,那么设置成手动或禁用,这样你新插入一个U盘,可能系统没有任何提示。
Smart Card/ Smart Card Removal Policy
如果你没有使用Smart Card,建议设置成禁用。
SNMP Trap
允许你的机器处理简单网络管理协议,很多网管协议是基于SNMP的。不是网管的话建议关闭。
SSDP Discovery
搜索使用了SSDP发现协议的一些设备,比如一些非即插即用的设备,如果没有相关设备,可以关了它。
Tablet PC Input Service
启用 Tablet PC 笔和墨迹功能,非Table PC及不使用手写板就可以关掉它。
TCP/IP NetBIOS Helper
使得你可以在计算机之间进行文件和打印机共享、网络登录。不需要可关闭。
Telephony
Adsl拨号就要用到这个服务,如果是路由器上网,就可以关了它。
Thread Ordering Server
提供特别的线程排序和调度服务,如果用不上,可以设置成手动,但不建议设置成自动。
TPM Base Services
可以设置成手动,如果你没有使用带TPM模块的计算机,可以禁用掉。
Virtual Disk
提供用于磁盘、卷、文件系统和存储阵列的管理服务。提供存储设备软件卷和硬件卷的管理,不要将其设置成禁用 。
WebClient
简单的说如果你不需要Web目录或类似功能,就可以关掉它。
Windows Backup
提供 Windows 备份和还原功能。Windows备份和版本恢复功能,一直都不好使,可以关掉。
Windows Biometric Service
如果你没有使用生物识别设备,如指纹识别系统,该功能就可以放心禁用,否则保持默认。
Windows CardSpace
像Smart Card一样的个人标识管理,.NET Framework 3.0提供的一个WCF编程模型。一般用户可以关闭。
Windows Connect Now - Config Registrar
无线网络要用的东西,如果没有,就关上它。
Windows Defender
可以加强安全,防范木马和一些恶意程序,最主要的是免费。不需要可以关闭。
Windows Error Reporting Service
没人喜欢错误,对你和微软而言,错误报告传送过去都没什么用。关了它。
Windows Firewall
Windows 防火墙不用多说什么了。如果不需要就禁用。
Windows Image Acquisition (WIA)
专门为扫描仪和数码相机等提供图像捕获和获取功能。有就开着,没有就关。
Windows Media Center Service Launcher/ Windows Media Center Receiver Service / Windows Media Center Scheduler Service
通过网络为Windows Media Extender(像XBox)等传送多媒体文件,建议禁止,除非你需要这个功能。
Windows Modules Installer
如果你不使用Windows Updates,那么可以禁止这个服务。
Windows Time
和服务器同步时间的,一般我都关闭它。
Windows Update
这个功能取决于你了,它和Background Intelligent Transfer Service、Modules Installer服务关联。
WinHTTP Web Proxy Auto-Discovery Service
该服务使应用程序支持WPAD协议的应用,因为大多数的情况下不会用到。建议关闭。
Wired AutoConfig
此服务对以太网接口执行 IEEE 802.1X 身份验证。其实很多的时候,还是要自己设置的。默认即可。
WLAN AutoConfig
不用无线网络可以关掉
posted @ 2010-07-13 22:17 Eric_jiang 阅读(1718) | 评论 (0)编辑 收藏

当 需要分析某个查询的效能时,最好的方式之一查看这个查询的执行计划。执行计划描述SQL Server查 询优化器如何实际运行(或者将会如何运行)一 个特定的查询。

查 看查询的执行计划有几种不同的方式。它们包括:

SQL Server查询分析器里有一个叫做显示实际执行计划的选项(位于查询下拉菜单中)。如果打开了这个选项,那么 无论何时在查询分析器中运行一个查询,都会得到一个显示在单独窗口的查询执行计划(以图形的格式)

如果只是想看下执行计划而不想 运行查询,那么可以选择显示预估的执行计划选项(位于查询下拉菜单中)。当选择这个选项后,执行计 划会马上显示出来(以图形的格式)。两者的不同之处在于当实际运行一个查询时,当前的服务器上的运算也会被考虑进去。大多数情况下,两种方 式产生的执行计划产生的结果是相似的。

当建立一个SQL Server Profiler追踪时,可以收集的一个事件是MISC: Execution Plan.这个信息(以文本的形式)显示查询优化器用来执行查询 的计行计划。

可以在查询分析器上执行SET SHOWPLAN_TEXT ON命令。这条命令被执行后,所有在当前这个查询分析器会话中执行的查询都不会运行,而是会显示一个基于文本的 执行计划。执行某条用到临时表的查询时,必须在执行查询先运行SET STATISTICS PROFILE ON语句。

上面这些选项中,我更喜欢使用显示实际执行计划这个选项。它以图形的方式输 出信息,并且考虑到了当前服务器上的那些运算。[7.0, 2000] Updated 8-5-2005

*****

如果在执行计划中看到如下所示 的任何一项,就应该将它们视作警告信号并调查它们以找出潜在的性能问题。从性能方面来说,下面所示的每一项都是不理想的。

Index or table scans(索引或者表扫描)可能意味着需要更好的或者额外 的索引。

Bookmark Lookups(书签查找)考虑修改当前的聚集索引,使用复盖索引,限制SELECT语句中的字段数量。

Filter(过滤)WHERE从句中移除用到的任何函数, 不要在SQL语句中包含视图,可能需要额外的索引。

Sort(排序)数据是否真的需要排序?可否 使用索引来避免排序?在客户端排序是否会更加有效率?

无一例外地避免这些操作是不可 能的,但是避免得越多,查询性能就会越快。[7.0,2000,2005]

*****

如果有在存储过程中或者其它T-SQL批处理代码中用到了临时表, 就不能在查询分析器或Management Studio使用显示预估的执行计划选项来评估查询。必须实际运 行这个存储过程或者批处理代码。这是因为使用显示预估的执行计划选项来运行一个查询时,它并没有实际被运行,临时表也没有创建。由于临时表没 有被创建,参考到临时表的代码就会失败,导致预估的执行计划不能成创建成功。

从另一方面来说,如果使用的是 表变量而不是临时表,则可以使用显示预估的执行计划选项。[7.0,2000,2005] Updated 8-5-2005

*****

 

如果在查询分析器或Management Studio中对一个非常复杂的查询的执行计划进行分析,可能会觉得它的执行计划既难于看懂也难于分析。那么,按照查询的逻辑将它拆分成几 个部分,然后分别对这些部分进行分析会容易得多。[7.0,2000,2005] Updated 8-5-2005

*****

 

图形执行计划并不总是容易读懂 和解释。查看执行计划时记住如下几点:

非常复杂的执行计划会被分成多 个部分,它们分别列出在屏幕上。每个部分分别代表查询优化器为了得到最终结果而必须执行的单个处理或步骤。

执行计划的每个步骤经常会被拆 分成一个个更小的子步骤。不幸的是,它们是从右至左显示在屏幕上的。这意味着你必须滚动到图形执行计划的最右边去查看每个步骤是从哪儿开始的。

每个步骤与子步骤间通过箭头连 接,藉此显示查询执行的路径。

最后,查询的所有部分在屏幕顶 部的左边汇总到一起。

如果将鼠标移动到任何执行计划 任何步骤或者子步骤的上面,就会显示一个弹出式窗口,上面显示该步骤或子步骤的更加详细的信息。

如果将鼠标移动到连接步骤或子 步骤的箭头上,就可以看到一个弹出式窗口,上面显示有多少笔记录从一个步骤或子步骤移动到另一个步骤或子步骤。

[7.0, 2000, 2005] Updated 8-5-2005

 

 

图形执行计划上连接每个图标的箭头粗细不同。箭头的粗细表示每个图标之间移动的数据行数量以及数据行大小移动所需的相对成本。箭头越粗,相对成本就越高。

 

可以使用这个指示器来快速测量一个查询。你可能会特别关注粗箭头以了解它如何影响到查询的效能。例如,粗线头应该在图形执行计 划的右边,而非左边。如果看到它们在左边,就意味着太多的数据行被返回,这个执行计划也不是最佳的执行计划。[7.0,2000,2005]

*****

 

执行计划的每个部分都被分配了一个成本百分比。它表示这个部分耗用了整个执行计划的多少资源。当对一个执行计划进行分析的时候,应该将精力集中于有着高成本百分比的那些部 分。这样就可以在有限的时间里找到可能性最大的问题,从而回报了你在时间上的投资。[7.0, 2000, 2005]

*****

 你可能会注意到一个执行计划的某些部分被执行了不止一次。作为执行计划分析的一部分,应该将你的一些时间集中在任何执行了超过一次的那些部分上,看看是否有什么方式减少它们执行的次 数。执行的次数越少,查询的速度就越快。[7.0, 2000, 2005]

*****

 在执行计划中你可以看到I/OCPU成本。它们没有实际的意义,例如代 表特定资源的使用量。查询优化器使用这些数字来做出最佳选择。它们可用来参考的一个意义是,较小的I/OCPU成本比较大的I/OCPU成本使用更少的服务器资源。[7.0, 2000, 2005]

*****

 

查看SQL Server图形执行计划时,可以查找的非常有 用的一个东西就是查询优化器如何为给定的查询使用索引来从表中获取数据。通过查看是否有用到索引,以及索引如何被使用,都有助于判断当前的索引是否使得查询执行得尽可能的快。

将鼠标移到图形执行计划上的表名(以及它的图标)上面,就会弹出一个窗口,从它上面可以看到一些信息。这些信息让你知道是否有用到索引来从表中获取数据,以及它是如何使用的。 这些信息包括:

·     Table Scan(表扫描):如果看到这个信息,就说明数据表上没有聚 集索引,或者查询优化器没有使用索引来查找。意即资料表的每一行都被检查到。如果资料表相对较小的话,表扫描可以非常快速,有时甚至快过使用索引。

因此,当看到有执行表扫描时,第一件要做的事就是看看数据表有多少数据行。如果 不是太多的话,那么表扫描可能提供了最好的总体效能。但如果数据表大的话,表扫描就极可能需要长时间来完成,查询效能就大受影响。在这种情况下,就需要仔 细研究,为数据表增加一个适当的索引用于这个查询。

假设你发现某查询使用了表扫描,有一个合适的非聚集索引,但它没有用到。这意味 着什么呢?为什么这个索引没有用到呢?如果需要获得的数据量相对数据表大小来说非常大,或者数据选择性不高(意味着同一个字段中重复的值很多),表扫描经常会比索引扫描快。例如,如果一个数据表有10000个数据行,查询返回1000行,如果这个表没有聚集索引的话,那么表扫描将比使用一个非聚集索引 更快。或者如果数据表有10000个数据行,且同一 个字段(WHERE条件句有用到这 个字段)上有1000笔重复的数据,表扫描也会比使用非聚集索引更快。

查看图形执行计划上的数据表上的弹出式窗口时,请注意预估的资料行数(Estimated Row Count)”。这个数字是查询优化器作出 的多少个数据行会被返回的最佳推测。如果执行了表扫描且预估的数据行数数值很高的话,就意味着返回的记录数很多,查询优化器认为执行表扫描比使用可用的非聚集索引更快。

·     Index Seek(索引查找):索引查找意味着查询优化器使用了数据表上 的非聚集索引来查找数据。性能通常会很快,尤其是当只有少数的数据行被返回时。

·     Clustered Index Seek(聚集索引查找):这指查询优化器使用了数据表上的聚集索引来查找数据,性能很快。实际上,这是SQL Server能做的最快的索引查找类型。

·     Clustered Index Scan(聚集索引扫描):聚集索引扫描与表扫描相似,不同的是聚集索引扫描是在一个建有聚集索引的数据表上执行的。和一般的表扫描一样,聚集索引扫描 可能表明存在效能问题。一般来说,有两种原因会引此聚集索引扫描的执行。第一个原因,相对于数据表上的整体数据行数目,可能需要获取太多的数据行。查看预估的数据行数量(Estimated Row Count)”可以对此加以验证。第二个原 因,可能是由于WHERE条件句中用到的字 段选择性不高。在任何情况下,与标准的表扫描不同,聚集索引扫描并不会总是去查找数据表中的所有数据,所以聚集索引扫描一般都会比标准的表扫描要快。通常 来说,要将聚集索引扫描改成聚集索引查找,你唯一能做的是重写查询语句,让语句限制性更多,从而返回更少的数据行。

[7.0, 2000, 2005]

绝大多数情况下,查询优化器会对连接进行分析,按最有效率的顺序,使用最有效率 的连接类型来对数据表进行连接。但并不总是如此。在图形执行计划中你可以看 到代表查询所使用到的各种不同连接类型的图标。此外,每个连接图标都有两个箭头指向它。指向连接图标的上面的箭头代表该连接的外部表,下面的箭头则代表这 个连接的内部表。箭头的另一头则指向被连接的数据表名。

 

有时在多表连接的查询中,箭头的另一头指向的并不是一个数据表,而是另一个连接。如果将鼠标移到指向外部连接与内部连接的箭头 上,就可以看到一个弹出式窗口,告诉你有多少数据行被发送至这个连接来进行处理。外部表应该总是比内部表含有更少的数据行。如果不是,则说明查询优化器所 选择的连接顺序可能不正确(下面是关于这个话题的更多 信息)

 

首先,让我们来看看连接类型。SQL Server可以使用三种不同的技术来连接资料表:嵌套循环(nested loop),散列(hash),以及合并(merge)。一般来说,嵌套循环是最快的连接类型,但如果不可能使用嵌套循环的话,则会用到散列或者合并作为合适的连接类型。两者都比嵌 套循环连接慢。

 

当连接大表时,则合并连接可能是最佳选项,而非嵌套循环连接。唯一的明确这一点的方式是对两者都进行测试以查看哪一个最有效 率。

 

如果你怀疑某个查询速度慢的原因可能是因为它所使用的连接类型不理想,那么你可以使用连接提示来复盖查询优化器的选择。在使用 连接提示之前,你需要花费一些时间去了解一下每种连接类型以及它们的工作方式。这是一个复杂的话题,超出了本文的讨论范围。

 

查询优化器选择最有效率的连接类型来连接数据表。例如,嵌套循环连接的外部表应该是连接的两个表中较小的那个表。散列连接也是 一样,它的外部表应该是较小的那个表。如果你觉得查询优化器选择的连接顺序是错误的,可以使用连接提示来复盖它。

 

很多情况下,唯一的确认使用连接提示改变连接类型或连接顺序是提升还是降低了效能的方式,就是对它们进行测试,看看发生了什 么。[7.0, 2000, 2005]

*****

 

如果你的SQL Server有多个CPU,并且没有修改SQL Server的默认设置来限制SQL Server使用服务器上所有CPU的能力,那么查询优化器会考虑使用平行处 理(parallelism)来执行某些查询。平行处理指在多个CPU上同时运行一个查询的能力。很多情况下,一个运行在多个处理器上的查询比仅运行在单个处理器上的查询要快,但并不总是这样。

 

查询优化器并不会总是使用平行处理,即使在它能使用的时候。这是因为查询优化器在决定使用平行处理前会考虑到各种不同的因素。 例如当前SQL Server上处于活动状态的连接数量,CPU忙碌程度,是否有足够的内存来运行平行化查询,需要处理的数据行数量,以及这个查询的类型。查询优化器收集到这些真实的数据 后,再决定平行处理是不是运行这个查询的最佳选择。你可能会发现,某次一个查询没有用到平行处理,但稍后某次再次运行同样的查询时,却又用到了平行处理。

 

有时,使用多个处理器所需的花费会大于使用它们能所能节省的资源。尽管查询处理器的确会衡量使用平行查询的正反两面的影响,但 它的猜想并不总是正确的。

 

如果怀疑平行处理防碍了某条查询的性能,你可以使用OPTION (MAXDOP 1)提示来关闭该查询的平行处理。

决定是否使用平行处理的唯一方式是通过这两种方式对查询进行测试,看看发生了什么。[7.0, 2000, 2005]

*****

 

查看图形执行计划时,你可能会发现某个图标的文字用红色显示,而非通常情况下的黑色。这意味着相关的表的一些统计数据遗失,统计数据是查询优化器生成一个好的执行计划所必须的。

 

遗失的统计数据可以通过右键 这个图标,并选择创建遗失的统计资料来创建。这时会弹出创建遗失的统计数据对话框,通过它可以很容易地 创建遗失的统计数据。

 

当可以选择去更新遗失的统计 资料时,应该总是这样做,因为这样极有可能让你正在分析的查询语句从中获得效能上的好处。[7.0, 2000, 2005]

*****

 

有时你会在图形执行计划上看到标识了”Assert”的图标。这意味着查询优化器正在验证查询语句是否有违反引用完整性或者条件约束。如果没有,则没有问题。但如果有的话,查询优化器将无 法为该查询建立执行计划,同时会产生一个错误。[7.0, 2000, 2005]

*****

 

你常常会在图形执行计划上看到标识成书签查找(Bookmark Lookup)”的图标。书签查找相当常见。书签查找的本质是告诉你查询处理器必须从数据表或者聚集索引中来查找它所需要的数据行,而不是从非聚集索引 中直接读取。

 

打比方说,如果一个查询语句的SELECT,JOIN以及WHERE子句中的所有字段,都不存在于那个用来定位符合查询条件的数据行的非聚集索引中,那么查询优化器就不得不做额外的工作在数据表 或聚集索引中查找那些满足这个查询语句的字段。

 

另一种引起书签查找的原因是使用了SELECT *。由于在绝大多情况下它会返回比你实际所需更多的数据,所以应该永不使用SELECT *.

 

从性能方面来说,书签查找是不理想的。因为它会请求额外的I/O开销在字段中查找以返回所需的数据行。

 

如果认为书签查找防碍了查询的性能,那么有四种选择可以用来避免它:可以建立WHERE子句会用到的聚集索引,利用索引交集的优势,建立覆盖的非聚集索 引,或者(如果是SQL Server 2000/2005企业版的话)可以建立索引视图。如果这些都不可能,或者使用它们中的任何一个都会 耗用比书签查找更多的资源,那么书签查找就是最佳的选择了。[7.0, 2000, 2005]

 

有时查询优化器需要在tempdb数据库中建立临时工作表。如果是这样的话,就意味着图形执行计划中有标识成Index Spool, Row Count Spool或者Table Spool的图标。

 

任何时候,使用到工作表一般都会防碍到性能,因为需要额外的I/O开销来维护这个工作表。理想情况下应该不要用到工作表。不幸的是并不能总是避免用到工作表。有时当使用工作表比其它选择更有效 率时,它的使用实际上会增强性能。

 

不论何种情况,图形执行计划中的工作表都应该引起你的警觉。应该仔细检查这样的查询语句,看看是否有办法重写查询来避免用到工 作表。有可能没有办法。但如果有的话,你就朝提升这个查询的性能方面前进了一步。[7.0, 2000, 2005]

*****

 

在图形执行计划上看到流聚合(Stream Aggregate)图标就意味着有对 一个单一的输入进行了聚合。当使用了DISTINCT子句,或者任何聚合函数时,如AVG, COUNT, MAX, MIN,或者SUM等,流聚合操作就相当常见。 [7.0, 2000, 2005]

*****

 

查询分析器与Management Studio不是唯一的可以生成显示查询执行计划的工具。SQL Server Profiler也可以显示执行计划,但格式 是文本形式的。使用SQL Server Profiler来显示执行计划的一个优势是,它能为实际运行的大量查询产生执行计划。如果使用查询分析器和Management Studio,则一次只能运行一个。

 

使用Profiler捕获、显示执行计划时,必须使用如下的配置生成一个追踪:

捕获事件

·     Performance: Execution Plan

·     Performance: Show Plan All

·     Performance: Show Plan Statistics

·     Performance: Show Plan Text

 

显示的字段

·     StartTime

·     Duration

·     TextData

·     CPU

·     Reads

·     Writes

 

过滤条件

·     Duration。你会想指定最大的查询执行时间,例如5秒钟,由此避免得到太大量的数据。

 

当然,你可以在你的追踪中捕获更多的没有例在上面的信息,上面例出的只是一个指南而已。但必须记住不要去捕获太多的数据,否 则,追踪的运行会影响服务器的性能。[7.0, 2000, 2005]

*****

 

如果在查询中使用了OPTION FAST提示,那就必须小心执行计划的结果可能不是你所期望的。这时你所看到的执行计划基于使用了FAST提示的结果,而不是整个查询语句的实际执行计划。

 

FAST提示用来告知果询优化器尽可能快地返回指定行数的数据行,即便这样做 会防碍查询的整体性能。使用这个提示的目的在于为使用者快速返回特定行数的记录,由此让他们产生速度非常快速的错觉。。当返回指定行数的数据行后,剩余的 数据行按照它们通常的速度返回。

 

因此,如果使用了FAST提示,那么生成的执行计划只是基于那些FAST返回的数据行,而非查询要返回的所有数据行。如果想看所有数据行的执行计划,那么就必须移除这个FAST提示。[2000,2005]

posted @ 2010-07-07 22:28 Eric_jiang 阅读(1071) | 评论 (0)编辑 收藏

之前没哪次实践过,只是听一堆人说不可以或者不成功,今天测试了下,成功实现。
OS:win2003
Browse:IE6,Mozilla1.5,Netscape8.0,Friefox1.0,Opera8.51

步骤:
1、在iis新建站点3个www.goalercn.com(和 goalercn.com),img.goalercn.com,blog.goalercn.com
2、在www.goalercn.com下建立文件testcookies.asp,代码如下:
<%
Response.Cookies("Type") = "Test Cookies"
Response.Cookies("Type").Expires = date()+30
Response.Cookies("Type").Domain = ".goalercn.com"
Response.Cookies("Type").Secure = False
Response.Write Request.Cookies("Type")
%>

 3、在ad.goalercn.com下建立文件testcookies.asp,代码如下:
<%Response.Write Request.Cookies("Type")%>

 4、在blog.goalercn.com下建立文件testcookies.asp,代码同上
5、因为是本机测试,修改hosts文件,把4个域名都指向到127.0.0.1,也就是添加如下内容:
    127.0.0.1     ad.goalercn.com
    127.0.0.1     blog.goalercn.com
    127.0.0.1     www.goalercn.com
    127.0.0.1     goalercn.com
6、关闭所有浏览器,开ie,打开http://www.goalercn.com/demo/testcookies.asp,显示出文本内 容:Test Cookies
7、新建窗口,打开http://ad.goalercn.com/temp/testcookies.asp,显示出文本内 容:Test Cookies
8、新建窗口,打开http://blog.goalercn.com/temp/testcookies.asp,同样显示出如上文本内容
9、换其他4个浏览器,都成功。

注意点:
1、Response.Cookies("Type").Secure = False,Secure属性一定要是false,或者直接不执行这行,如果 Secure = True,则ad和blog的2级域名是取值不了。
2、Response.Cookies("Type").Domain = ".goalercn.com",domain的值,我设置 为"goalercn.com",也就是没有前面的点,在IE下成功
其他4个浏览器没测试。
3、path我猜是不应该设置的。
4、在局域网内其他机器上,修改host指向到我机器的IP,取值成功。
5、在局域网另外一台机器上架设ad.goalercn.com,把testcookies.asp文件copy过去,同时修改host到当前机器,取值 成功
posted @ 2010-07-05 14:51 Eric_jiang 阅读(895) | 评论 (3)编辑 收藏

我们知道Struts2会将Action中的属性存放到ValueStack对象中,在通过Action转发的页面中,我们可以通过Struts2的标签<s:property/>来输出这些值,但是这样得到的值却仅限于输出显示,不能进行进一步的操作,那么我们应该怎样得到ValueStack中的值又能对它进行其他操作呢?

首先,我们需要了解Struts2是将Action中的属性全部封装在一个叫做struts.valueStack的请求属性中,然后我们就可以通过下面的代码来获取这些值了:

 

 someThing是Action中属性值的名称。

posted @ 2010-06-30 21:18 Eric_jiang 阅读(1605) | 评论 (1)编辑 收藏

M

S SQL2005对2000进行了很大的改进,而用户关系这部分也变得相当复杂了,很多朋友都对此一知半解!下面,我将把我应用中总结的和大家分享下,先从概念入手,希望对不理解的朋友有点提示。

今天我们要说的包括服务器登录名Server Login,服务器角色Server Role,数据库用户DB User,数据库架构DB Schema,数据库角色DB Role 。以上几个名词应该从服务器与数据库来区分,服务器包含一到多个数据库,其中:

服务器登录名,指有权限登录到某服务器的用户;

服务器角色,指一组固定的服务器用户,默认有9组;

  • 登录名一定属于某些角色,默认为public
  • 服务器角色不容许更改
  • 登录后也不一定有权限操作数据库

数据库用户,指有权限能操作数据库的用户;

数据库角色,指一组固定的有某些权限的数据库角色;

数据库架构,指数据库对象的容器;

  • 数据库用户对应于服务器登录名以便登录者可以操作数据库
  • 数据库角色可以添加,可以定制不同权限  
  • 数据库架构,类似于数据库对象的命名空间,用户通过架构访问数据库对象

而通过下图可以让这些概念清晰一些:

    

即:

  1. 服务器登录名属于某组服务器角色;
  2. 服务器登录名需要于数据库的用户映射后才拥有操作数据库的权限
  3. 数据库用户属于某组数据库角色以获取操作数据库的权限
  4. 数据库角色拥有对应的数据库架构,数据库用户可以通过角色直接拥有架构
  5. 数据库用户有默认架构,写SQL语句可以直接以“对象名”访问
  6. 非默认架构则要以“架构名.对象名”访问

因此,新建一个非SA账户并建立数据库的过程可以如下:

1、新建登录名Login1

 

2、新建数据库DB1

 

3、新建DB1的架构Schema1


 

4、新建BD1的用户User1,登录名对应Login1,默认架构选择Schema1,角色选择db_owner


 

5、在登录名Login1的属性窗口里选择“用户映射”,勾选DB1,在用户里填写User1,默认架构选择"Schema1"


 

6、至此,新建表名会是Schema1.Table1,其他对象也如此


 


 

7、当然还可以新建其他架构的对象Schema2,只有User1拥有该架构,一样可以访问,如Schema2.Table2

值得注意的是,当为登录映射数据库用户的时候,多个数据库可以有相同名称的用户,而单独为某个数据库新建的用户,如User1,则在其他数据库里不允许同名。

posted @ 2010-06-29 12:31 Eric_jiang 阅读(618) | 评论 (0)编辑 收藏

仅列出标题
共57页: First 上一页 47 48 49 50 51 52 53 54 55 下一页 Last