Month: December 2014

高并发应用中的MySQL:尽量不要表连接

对于高并发应用中的MySQL,按照我的经验,尽量不要表连接;MySQL Optimizer在处理表连接时有时很不智能,搞出个大坑。比如这个。 在需要表连接的场景,尽量把它拆解掉,这就叫做 Join Decomposition. 个人常用的办法有两个: 1.冗余 2.分成两步执行: 先查出符合条件的A表的ID,再根据这些ID使用IN字句去B表中查询。 消除表连接还有个附加好处是两个表不一定要放在同一个库里,这样你做垂直分库会比较自由。

MySQL: Explain Plan中的Using Where意思是扫描数据后扔掉了一部分

Using Where意思是 扫描(examine)数据后扔掉了一部分,只返回剩下的。常见的例子是根据无索引的字段进行搜索。 select * from user where description = ‘to be a better man’ 这时MySQL必须把所有数据找出来,然后“使用Where条件”判断一下description是不是"to be a better man"; 等找到之后再把不符合条件的扔掉。

MySQL不支持游标(在线ResultSet)

有的数据库支持游标。你输入一个select * from t, 拿到一个ResultSet对象,要求取10行,数据库就临时给你找出10行;再取下一个10行,数据库再给你查询出10行。 MySQL不支持这种机制。你输入select * from t, MySQL就会把所有数据都查出来再给你。在全部查完之前,根本停不下来。这就是 "limit"关键字非常重要的原因。

SQL性能问题可以归结为两大类

1.查询出了过多数据。 比如只需查某列数据,应用却要求每行都返回所有字段。 2.数据库扫描了过多数据,虽然不一定全部返回。 如:只需查一行数据,由于没有索引导致全表扫描。

前后端结合,让DataTables页面接受url中的过滤参数

一个DataTables页的典型流程是: 1. 访问一个url让系统渲染一个普通的前端页面 2. 页面上内含一段javascript, 生成DataTables对象,然后立即向后端请求数据,最后在本页中填充数据 默认情况下DataTables不做任何初始过滤,待用户在searchField输入框中输入值后,才会做过滤。 现在的需求的,在上述#1步的url中即传入参数,如list.jsp?userId=123. 期望在第2步结束后, 1. userId对应的searchField输入框中显示123 2. 显示的数据已按userId=123过滤 网上搜了下,没看到较好的方案。最终自己使用了这样一套做法: 1. 通过MVC后端把userId=123的值渲染回JSP的searchField输入框中 //以SpringMVC为例 model.put(“userId”, request.getParameter(request, “userId”)); <!– list.jsp –> <tfoot> <tr> <th> <input type=”text” class=”searchField” size=”1″ placeholder=”精确匹配” value='<c:out value=”${userId}”/>’> </th> <tr> … </tfoot> 2. 在dataTable对象加载完后,立即轮询一下所有searchField, 如果有值,触发一次搜索。 <!– list.jsp –> <script> table.columns().eq( 0 ).each( function ( colIdx ) { var footerColumn = …

前后端结合,让DataTables页面接受url中的过滤参数 Read More »

eclipse代码生成模板:把一个bean的属性复制到另一个bean

生成代码,把一个bean的属性复制到另一个bean (两个bean未必同类型,但有一些共同的属性) ${:import(java.lang.reflect.Method)} public static void main(String args[]) { Class<?> destinClass = ${DestinBean}.class; String destinObj = "${destinBean}"; Class<?> srcClass = ${SrcBean}.class; String srcObj = "${srcBean}"; Method[] destinMethods = destinClass.getMethods(); Method[] srcMethods = srcClass.getMethods(); for (Method destinMethod : destinMethods) { if (destinMethod.getName().startsWith("set") && destinMethod.getParameterTypes().length == 1) { String setterName = destinMethod.getName(); String prop = setterName.substring("set".length()); if …

eclipse代码生成模板:把一个bean的属性复制到另一个bean Read More »

数据库:通过分槽减少计数字段的竞争

一个红人发了一个帖子,每秒对这个帖子的“赞”数可能会很高。如果这些赞请求都落到数据库中的同一条记录上,会导致对同一条记录过高的临界访问(因为有锁),导致排队。 解决办法是把这1条记录拆成100条记录,更新赞数时可能会更新到其中任意一条记录上。这样并发访问的竞争就会松很多。当需要显示总赞数时,临时把100条记录的总赞数累加起来即可。 对于NoSQL数据库和关系数据库,实现这种分槽(slot)机制都不难。对于MySQL数据库,最简单的做法是: insert into post_like_counter(post_id, slot, like_count) values (100, rand() * 100, 1) on duplicate key update like_count = like_count + 1 其中slot是槽号(1-100).  <post_id, slot>组成一个唯一键。

MySQL: Check Table, Repair Table, Analyze Table和Optimize Table

check table a123 检查索引状态是否正常,没有重复唯一键之类的 repair table a123 修复索引。InnoDB不支持这个命令,可以通过执行一次alter table engine达到同样的目的: alter table a123 engine = INNODB analyze table a123 为优化器提供本表索引的统计数据 optimize table a123 把分散存储(fragmented)的数据和索引重新挪到一起(defragmentation),对I/O速度有好处。 InnoDB的索引无法使用这个命令来deframent, 你也可以通过执行一次alter table engine达到同样的目的: alter table a123 engine = INNODB

MySQL: 联合索引在order by中的使用

对于联合索引,要注意索引字段在order by中出现的方式,否则可能会导致索引失效。下面举例说明。 下面这张表有个联合索引: <a1,a2,a3>,并且表里有100万行数据 create table a123( id bigint unsigned auto_increment not null, a1 varchar(50) not null, a2 varchar(50) not null, a3 varchar(50) not null, b1 varchar(50) not null, b2 varchar(50) not null, b3 varchar(50) not null, primary key(id), index idx_a_123(a1, a2, a3) ) explain select * from a123 order by a1 asc limit 100; …

MySQL: 联合索引在order by中的使用 Read More »