表结构优化
表中尽量使用短字段、数字类型的列,
比如ip可以通过inet_aton函数转换成int型,转换规则,a.b.c.d 的ip number是:a * 256的3次方 + b * 256的2次方 + c * 256的1次方 + d * 256的0次方;
mysql> select inet_aton('255.255.255.255'); +------------------------------+ | inet_aton('255.255.255.255') | +------------------------------+ | 4294967295 | +------------------------------+ mysql> select inet_ntoa(4294967295); +-----------------------+ | inet_ntoa(4294967295) | +-----------------------+ | 255.255.255.255 | +-----------------------+
垂直分表,即将原表中的列根据业务拆分为多个表,这样带来的好处是将不同业务的查询分散在不同的表中,坏处是当有业务需要多个表的数据时需要join;
水平分表,即将表中数据按照某字段的某些规律(如将id尾字符取16进制的后4位,0-9,a-f进行分表)拆分为多个表,相同的业务在处理不同的客户请求时,就可能会被分配至不同的表中,有利于减轻db复合;
InnoDB缓存池
mysql> show variables like 'innodb%pool%'; +-------------------------------------+----------------+ | Variable_name | Value | +-------------------------------------+----------------+ | innodb_additional_mem_pool_size | 8388608 | | innodb_buffer_pool_dump_at_shutdown | OFF | | innodb_buffer_pool_dump_now | OFF | | innodb_buffer_pool_filename | ib_buffer_pool | | innodb_buffer_pool_instances | 8 | | innodb_buffer_pool_load_abort | OFF | | innodb_buffer_pool_load_at_startup | OFF | | innodb_buffer_pool_load_now | OFF | | innodb_buffer_pool_size | 134217728 | +-------------------------------------+----------------+
可以通过SET GLOBAL innodb_buffer_pool_size=xxx;进行设置。
innodb_buffer_pool_dump_at_shutdown用于在mysql关闭时保存缓存中的热数据,innodb_buffer_pool_load_at_startup用于在mysql开启时恢复保存的热数据至缓存。
char、varchar、text、blob
char在存储时有固定的长度(1-255,即一个字节),多于设定长度的字符串会被截取,少于设定的长度会被填充,固定长度的优势在于插入速度快(必须整行都是固定长度);
varchar在存储时长度可变(1-65535,64k,即两个字节全1的情况,该大小表示字节数而不是字符数,65535包括表示长度的两个字节,VARCHAR(86)存储中文就是3 × 85 + 1 = 256个字节,需要两个字节记录长度),多于设定长度的字符串会被截取,少于设定的长度不会被填充,变长的优势在于存储不确定长度字符串时,可以节省空间。
text与varchar类似,也是变长的,其又分为TINYTEXT
, TEXT
,MEDIUMTEXT
, and LONGTEXT,依次使用1、2、3、4个字节来表示长度
blob与text类似,又分为TINYBLOB
, BLOB
, MEDIUMBLOB
, and LONGBLOB,blob、text、varchar都不会截去末尾的空空白字符
char、varchar、text可以选择是否忽略大小写:
mysql> select 'abc'='Abc' COLLATE utf8_general_ci; +--------------+ | 'abc'='Abc' | +--------------+ | 1 | +--------------+ mysql> select 'abc'='Abc' COLLATE utf8_bin; +--------------+ | 'abc'='Abc' | +--------------+ | 0 | +--------------+
mysql中行的最大长度为65535(即2的16次方-1)个字节,列的最大长度受此限制,行中并不存储text、blob的内容,只是存储了其地址,在对text、blob建立索引时,必须指定索引前缀长度。注意,只有在表中的所有列都是固定长度时,char对于varchar的速度优势才会体现,否则char并不必varchar更高效。
如果插入的字符串的末尾有空格,char会抹去空格,varchar会保留空格。
char、varchar、text在进行比较操作时(比如=),都会舍去末尾的空格(LIKE属于模式匹配操作):
mysql> select 'abc'='abc '; +--------------+ | 'abc'='abc ' | +--------------+ | 1 | +--------------+ mysql> select 'abc' LIKE 'abc '; +--------------+ | 'abc' LIKE 'abc ' | +--------------+ | 0 | +--------------+
批量更新
jdbc
1 try{ 2 Class.forName("com.MySQL.jdbc.Driver"); 3 conn = DriverManager.getConnection(o_url, userName,password); 4 conn.setAutoCommit(false); 5 String sql = "INSERT user(user_name, password) VALUES (?, ?)"; 6 PreparedStatement prest =conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); 7 for(User user: users){ 8 prest.setString(1,user.getUserName); 9 prest.setString(2,user.getPassword); 10 prest.addBatch(); 11 } 12 prest.executeBatch(); 13 conn.commit(); 14 15 } catch (SQLException ex){ 16 Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null,ex); 17 } catch (ClassNotFoundException ex){ 18 19 Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null,ex); 20 }finally{ 21 conn.close(); 22 }
mapper.xml
1 <!-- 批量增加操作 --> 2 <insert id="batchInsert"> 3 insert into user(user_name,password) values 4 <!--@Param List<User> users--> 5 <foreach collection="users" item="item" index="index" separator=","> 6 (#{item.userName},#{item.password}) 7 </foreach> 8 </insert>
update、delete也类似。
参考:
https://dev.mysql.com/doc/refman/5.7/en/blob.html
https://dev.mysql.com/doc/refman/5.7/en/char.html
http://www.cnblogs.com/roverliang/p/6501768.html