
图书的变更(增,删,改)都需要修订索引,索引存在额外的维护成本
查找翻阅索引系统需要消耗时间,索引存在额外的访问成本
这个索引系统需要一个地方来存放,索引存在额外的空间成本
索引是不是越多越好?
如果我们的这个图书馆只是一个进出中转站,里面的新书进来后很快就会转发去其他图书馆而从这个馆藏中“清除”,那我们的索引就只会不断的修改,而很少会被用来查找图书
所以,对于类似于这样的存在非常大更新量的数据,索引的维护成本会非常高,如果其检索需求很少,而且对检索效率并没有非常高的要求的时候,我们并不建议创建索引,或者是尽量减少索引。
如果我们的书籍量少到只有几本或者就只有一个书架,索引并不会带来什么作用,甚至可能还会浪费一些查找索引所花费的时间。
所以,对于数据量极小到通过索引检索还不如直接遍历来得快的数据,也并不适合使用索引。
如果我们的图书馆只有一个10平方的面积,现在连放书架都已经非常拥挤,而且馆藏还在不断增加,我们还能考虑创建索引吗?
所以,当我们连存储基础数据的空间都捉襟见肘的时候,我们也应该尽量减少低效或者是去除索引。
索引该如何设计才高效?
如果我们仅仅只是这样告诉对方的:“帮我确认一本数据库类别的讲述 MySQL 的叫做《MySQL性能调优与架构设计》的书是否在藏”,结果又会如何呢?朋友只能一个大类区域一个大类区域的去寻找“数据库”类别,然后再找到 “MySQL”范畴,再看到我们所需是否在藏。由于我们少说了一个“计算机类”,朋友就必须到每一个大类去寻找。
所以,我们应该尽量让查找条件尽可能多的在索引中,尽可能通过索引完成所有过滤,回表只是取出额外的数据字段。
如果我们是这样说的:“帮我确认一本讲述 MySQL 的数据库范畴的计算机丛书,叫做《MySQL性能调优与架构设计》,看是否在藏”。如果这位朋友并不知道计算机是一个大类,也不知道数据库属于计算机大类,那这位朋友就悲剧了。首先他得遍历每个类别确认“MySQL”存在于哪些类别中,然后从包含 “MySQL” 书籍中再看有哪些是“数据库”范畴的(有可能部分是讲述PHP或者其他开发语言的),然后再排除非计算机类的(虽然可能并没有必要),然后才能确认。
所以,字段的顺序对组合索引效率有至关重要的作用,过滤效果越好的字段需要更靠前。
如果我们还有这样一个需求(虽然基本不可能):“帮我将图书馆中所有的计算机图书借来”。朋友如果通过索引来找,每次都到索引柜找到计算机书籍所在的区域,然后从书架上搬下一格(假设只能以一格为单位从书架上取下,类比数据库中以block/page为单位读取),取出第一本,然后再从索引柜找到计算机图书所在区域,再搬下一格,取出一本… 如此往复直至取完所有的书。如果他不通过索引来找又会怎样呢?他需要从地一个书架一直往后找,当找到计算机的书,搬下一格,取出所有计算机的书,再往后,直至所有书架全部看一遍。在这个过程中,如果计算机类书籍较多,通过索引来取所花费的时间很可能要大于直接遍历,因为不断往复的索引翻阅所消耗的时间会非常长。(延伸阅读:这里有一篇以前写的关于Oracle的文章,索引扫描还是全表扫描(Index Scan Or Full Table Scan))
所以,当我们需要读取的数据量占整个数据量的比例较大抑或者说索引的过滤效果并不是太好的时候,使用索引并不一定优于全表扫描。
如果我们的朋友不知道“数据库”这个类别可以属于“计算机”这个大类,抑或者图书馆的索引系统中这两个类别属性并没有关联关系,又会怎样呢?也就是说,朋友得到的是2个独立的索引,一个是告知“计算机”这个大类所在的区域,一个是“数据库”这个小类所在的区域(很可能是多个区域),那么他只能二者选其一来搜索我的需求。即使朋友可以分别通过2个索引检索然后自己在脑中取交集再找,那这样的效率实际过程中也会比较低下。
所以,在实际使用过程中,一次数据访问一般只能利用到1个索引,这一点在索引创建过程中一定要注意,不是说一条SQL语句中Where子句里面每个条件都有索引能对应上就可以了。
楼主这个过滤器只能过滤post请求,无法过滤get请求,我说的对吧。当给你form表单里的method设置为get或者使用默认值(默认值是get)的时候就无法处理中文问题,就是这里<form action="LoginAction" method="get">的method。因为tomcat的bug,使用get请求的时候无论pageEncoding设置成什么,都使用ISO8859-1编码。使用ISO8859-1编码的时候数据时以字符(问题就出现在这里,两个字符才是一个字节,一个字节才是一个中文)形式传递的。好了原因找到了
如果你还想用你的过滤器(但是你的过滤器存在隐患,还是不要用了)那做你将所有form中的method都设置成post即可。
如果你想用个完善的解决方案,那就给你讲一个。
解决方案如下:
首先:判断请求如果是post,直setCharacterEncoding(encode)
然后:如果请求时get。就遍历参数列表,将所有参数以ISO8859-1的方式转换成字节数组,然后再将字节数组构造成新的中文字符串。然后重新构造request请求对象,替换掉原来的请求。
下面的过滤器我一直在用,能转换各种请求的各种编码。
package com.zhangxuliang.filter
import java.io.IOException
import javax.servlet.Filter
import javax.servlet.FilterChain
import javax.servlet.FilterConfig
import javax.servlet.ServletException
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletRequestWrapper
public class PageEncodingFilter implements Filter {
private String encode
/**
* Request.java
* 对 HttpServletRequestWrapper 进行扩充, 不影响原来的功能并能提供所
有的 HttpServletRequest
* 接口中的功能. 它可以统一的对 Tomcat 默认设置下的中文问题进行解决而只
需要用新的 Request 对象替换页面中的
* request 对象即可.
*/
class Request extends HttpServletRequestWrapper
{
public Request(HttpServletRequest request) {
super(request)
}
/**
* 转换由表单读取的数据的内码.
* 从 ISO 字符转到 GBK.
*/
public String toChi(String input) {
try {
byte[] bytes = input.getBytes("ISO8859-1")
return new String(bytes, encode)
}
catch (Exception ex) {
}
return null
}
/**
* Return the HttpServletRequest holded by this object.
*/
private HttpServletRequest getHttpServletRequest()
{
return (HttpServletRequest)super.getRequest()
}
/**
* 读取参数 -- 修正了中文问题.
*/
public String getParameter(String name)
{
return
toChi(getHttpServletRequest().getParameter(name))
}
/**
* 读取参数列表 - 修正了中文问题.
*/
public String[] getParameterValues(String name)
{
String values[] =
getHttpServletRequest().getParameterValues(name)
if (values != null) {
for (int i = 0i <values.lengthi++) {
values[i] = toChi(values[i])
}
}
return values
}
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse
response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpreq = (HttpServletRequest)request
if(httpreq.getMethod().equals("POST")) {
request.setCharacterEncoding(encode)
} else {
request = new Request(httpreq)
}
chain.doFilter(request, response)
}
public void init(FilterConfig filterConfig) throws
ServletException {
encode = filterConfig.getInitParameter("encode")
}
}
web.xml配置如下
<filter>
<filter-name>PageEncodingFilter</filter-name>
<filterclass>com.zhangxuliang.filter.PageEncodingFilter
</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PageEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
费了这么大力气楼主要给好评哦!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)