MySQL: 长文本字段上建索引的问题与解决方案

文本字段越长,在这个字段上建索引的代价就越高。 为了解决这个问题,可以为这个字段配一个hash字段,然后在这个hash字段上建索引。 如, select * from log where url_hash= CRC32(‘http://bing.com?query=xxx&tp=xxx’ ) crc32()返回的值一般比较短,比较合适; 如果用md5或sha1做hash, 返回的值也很长,那就失去意义了。 不过,像上面这样写可能存在hash collision问题,所以应该加个原字段上的搜索条件,确保搜出来的是自己想要的: select * from log where url_hash= CRC32(‘http://bing.com?query=xxx&tp=xxx’ ) and url = ”http://bing.com?query=xxx&tp=xxx’ 另一种类似的方案是: 不用hash值,而用前缀。 这里有提到。

B+树索引可以使order by更快

select … order by a a上有索引时执行上面的语句,比a上没有索引时要快。因为B-树索引中各结点已经排好了序,数据库只需要沿着树中的叶子结点链路朝左或朝右走即可。

spring aop与aspectj到底什么关系?

首先,aspectj自己是一个完整的aop框架,没有spring也能跑起来。 其次,Spring AOP是一个专有名词。它专制一种运行机制,不是spring容器中的AOP都叫Spring AOP. Spring AOP中有很多看上去aspectj的东西,但Spring AOP在运行时,并不会触发aspectj的运行。Spring AOP是基于Proxy机制的,跟aspectj的compiler/weave机制其实没有半毛钱关系 。 虽然代码里这样声明了,但其实还是proxy-based的spring aop. <aop:aspectj-autoproxy/> 然而,Spring AOP又偏偏基本照搬了aspectj的领域概念和各种语法,并且直接使用了aspectj的相关jar库。 什么@PointCut, @Before等等,都是aspectjrt.jar中直接包括的类。官方文档说,这叫aspectj style. 引用 The @AspectJ style was introduced by the AspectJ project as part of the AspectJ 5 release. Spring interprets the same annotations as AspectJ 5, using a library supplied by AspectJ for pointcut parsing and matching. The AOP …

spring aop与aspectj到底什么关系? Read More »

写了一个excel处理工具sep4j – 一行代码完成excel的读写

sep4j – The Simple Excel Processing for Java 通过一次静态方法调用完成 excel <=> Collection<T> 的转换 Collection<T> => Excel Collection<User> users = Arrays.asList(user1, user2); LinkedHashMap<String, String> headerMap = new LinkedHashMap<String, String>(); headerMap.put("userId", "User Id"); //"userId" is a property of User class. // "User Id" will be the column header in the excel. headerMap.put("firstName", "First Name"); headerMap.put("lastName", "Last Name"); …

写了一个excel处理工具sep4j – 一行代码完成excel的读写 Read More »

poi – 生成excel时使表头比较醒目、好看

CellStyle style = sheet.getWorkbook().createCellStyle(); //置成黄色 style.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); style.setFillPattern(CellStyle.SOLID_FOREGROUND); //表头的边界线清晰可见 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); Row header = sheet.createRow(0); int columnIndex = 0; for (…) { Cell cell = createCell(header, columnIndex); cell.setCellValue(headerText); cell.setCellStyle(style); //表头cell的宽度适应文字 sheet.autoSizeColumn(columnIndex); columnIndex++; }

其实用JMeter就可以对mysql做性能测试了

我用Super Smack做过几次MySQL性能测试。虽然可以用,但这种用c写的程序存在安装困难的问题:在阿里云的centos上可以装的上,在aws上未必就装的上;配置起来也很难受,那些个smack文件,太古怪。 后来我发现,其实用JMeter的jdbc request就可以对mysql性能测试。我用的模式是: 引用 1. 在开发机器上(mac/ubuntu/windows)以gui方式配置好Test Plan, 并试运行。 2. 将test plan文件上传到无干扰无界面的linux测试机上,以non-gui方式在测试机上执行测试,再收集结果。 JMeter支持server模式:用本地的jmeter控制测试机上的jmeter, 直接在本机上启动、停止、查看结果,用起来非常顺手。但它有个问题:在测试过程中,测试机上的jmeter要不停地从本地机器获取测试数据,并返回采样数据到本地机器。这些数据流动会增加测试机上JMeter的负担,使qps偏低。 所以我还是选择了在测试机上使用non-gui模式这种方案。下面给个完整的例子,例示jmeter jdbc request的使用。 例示:用JMeter对MySQL进行压力测试 测试目标 使用普通varchar作为主键,比起使用自增数字类型作为主键,到底会慢多少?这个性能损失是不是可以忽略不计? 测试数据准备 建两张差不多的表,一个使用数字user_id作主键,一个直接使用user_name drop table if exists user_id_pk; drop table if exists user_name_pk; create table user_id_pk ( user_id bigint unsigned not null auto_increment , user_name varchar(50) not null description varchar(200) default null created_when datetime not null …

其实用JMeter就可以对mysql做性能测试了 Read More »

比较一个系统中两个模块的性能差别:不要同时压这两个模块

要比较一个系统中两个模块的性能差别(比如同一个库中的两个类似的表),有两种压测模式: 1. 一个test plan含两个senario, 执行一次,同时出两个模块的结果。 2. 搞两个test plan, 各带一个senario; 各执行一次,各出一个结果。 第一种模式很有吸引力,因为它可省下很多重复的配置工作;只执行一次,比较省时;像jmeter之类的还会直接给出直方图,以示比较。 然而,我的亲身经历表明,第1种模式由于公共资源占用问题会导致“大锅饭”效应: 同时压测两个模块,慢模块会占用过多公共资源(cpu, 内存,连接池等),导致快模块无法获得足够的资源因而也变慢。 这种模式下比较出来的结果并不准确。 所以,还是应该把两个测试互相隔离起来,搞两个 test plan,各带一个senario吧。 p.s. 如果你用jmeter,可以只写一个test plan,带两个sampler, 然后enable一个,disable另一个,这样每次执行时仍是隔离的。

分布式系统中的三种接口粒度

分布式系统中有三种接口粒度: 1. 内部用的domain service接口。这个接口最精致。   a. 出入参数跟数据库表有比较强的对应,基本上一个对象对应一张表。   b. 入参数据都假定已清洗,不必再校验。   c. 业务逻辑主要是CRUD+高度可重用的核心业务逻辑。   d. 返回数据一般是数据对象或者它们的类集。错误信息一般直接通过exception返回。 2. 供移动或web前端调用、或者供外部系统调用、面向use case的app service接口。这个接口最重。   a. 出入参数一般对应数据库中的多张表中的数据,还会有一些use case特有的字段,比如一个“帖子”对象中会给出“帖子作者的头像”、“当前用户能否删除本贴”、“帖子被评论次数”等。 这一层的数据对象是DTO(value object), 一般要从多个domain层对象的字段中组合而来。   b. 入参数据由用户直接输入或非可信系统输入,所以需要校验。   c.  业务逻辑一般需要通过组合多个domain service实现,比如 N个crud +  1个权限校验 + 1个展示层数据填充等,很难重用。   d. 返回数据一般是Result对象: 数据对象 + 错误码 + 错误信息, 不再抛exception. 3. 给内部可信系统调用的rpc service接口。这个接口的轻、重介于上面两种之间。   a. 出入参数包含的字段往往比domain层参数的稍多一点,比app层参数的少一些或少很多。   …

分布式系统中的三种接口粒度 Read More »

集群环境下慎用本地缓存

集群环境下慎用本地缓存。 用户1在机器A上看到100条记录,用户2在机器B上看到的却是90条记录。 你会说你的业务允许两边看到不一样。 是的,两个用户看到的不一样不要紧。 但是同一个用户看到不一样的话,用户体验会非常差,差到要骂人。 例子是:用户1在机器A上提交表单删除100条记录,服务端处理完毕后让浏览器跳转(Redirect after Submission),负载均衡将这个请求跳转到机器B上,机器B上的本地缓存没变,所以仍然是删除前的记录数。 用户1看到这个结果,脑子里只有一个想法:删除没起作用。 所以,集群环境下使用本地缓存,一定要保证同一个用户先后访问的是同一台机器。