<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ibugs (清水先生)</title>
    <link>https://ruby-china.org/ibugs</link>
    <description>其实我是一个厨师：）  Half Work, Half Life.</description>
    <language>en-us</language>
    <item>
      <title>MongoDB 与 MySQL  深入对比</title>
      <description>&lt;p&gt;由于公司系统使用 MongoDB，虽然之前了解，但并没有深入学习 MongoDB。见此机会，参考《MongoDB 权威指南》深入学习，结合对比 MySQL，加深对两种不同数据库的理解。特把学习过程记录和大家分享，欢迎批评指正。&lt;/p&gt;
&lt;h2 id="一、 表结构对比"&gt;一、表结构对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;表结构对比&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;表&lt;/td&gt;
&lt;td&gt;collections&lt;/td&gt;
&lt;td&gt;tables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;行&lt;/td&gt;
&lt;td&gt;documents&lt;/td&gt;
&lt;td&gt;rows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主键&lt;/td&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;id 与业务无关的值作为主键。如果没有显式地在表定义时指定主键，InnoDB 存储引擎会为每一行生成一个 6 字节的 ROWID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主键生成策略&lt;/td&gt;
&lt;td&gt;24 位的字符串 (time + machine + pid + inc),自己指定&lt;/td&gt;
&lt;td&gt;UUID, 自增&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;面向文档数据库&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;面向行数据库&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;约束&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;主键约束，外键约束&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="二、 数据类型对比"&gt;二、数据类型对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;数据类型对比&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;整形&lt;/td&gt;
&lt;td&gt;NumberInt("3"),NumberLong("3")&lt;/td&gt;
&lt;td&gt;TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;浮点&lt;/td&gt;
&lt;td&gt;默认使用 64 位浮点型数值&lt;/td&gt;
&lt;td&gt;FLOAT, DOUBLE, DECIMAL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;字符&lt;/td&gt;
&lt;td&gt;utf8 字符串&lt;/td&gt;
&lt;td&gt;VARCHAR, CHAR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日期/时间&lt;/td&gt;
&lt;td&gt;new Date(), 自新纪元依赖经过的毫秒数，不存储时区&lt;/td&gt;
&lt;td&gt;DATE, DATETIME, TIMESTAMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;不支持（null 与 null 不相等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;布尔类型&lt;/td&gt;
&lt;td&gt;true/false&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;正则表达式&lt;/td&gt;
&lt;td&gt;支持 { "x" : /foobar/i }&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数组&lt;/td&gt;
&lt;td&gt;支持 { "x" : ["a", "b", "c"]}&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;二进制数据&lt;/td&gt;
&lt;td&gt;支持   GridFS&lt;/td&gt;
&lt;td&gt;BLOB, TEXT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;代码片段&lt;/td&gt;
&lt;td&gt;{ "x" : function() { /&lt;em&gt;...&lt;/em&gt; / } }&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="三、 SHELL终端对比"&gt;三、SHELL 终端对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;对比项&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;启动&lt;/td&gt;
&lt;td&gt;mongo&lt;/td&gt;
&lt;td&gt;mysql -u root -p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查看库&lt;/td&gt;
&lt;td&gt;show dbs&lt;/td&gt;
&lt;td&gt;show databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;使用库&lt;/td&gt;
&lt;td&gt;use test&lt;/td&gt;
&lt;td&gt;use test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查看表&lt;/td&gt;
&lt;td&gt;show collections&lt;/td&gt;
&lt;td&gt;show tables&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="四、 查询对比"&gt;四、查询对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;查询对比&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;检索单列&lt;/td&gt;
&lt;td&gt;db.users.find({ "age" : 27 })&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE age = 27;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;检索多列&lt;/td&gt;
&lt;td&gt;db.users.find({ "age" : 27, "username" : "joe" })&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE age = 27 and username = 'joe';&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;指定需要返回的键&lt;/td&gt;
&lt;td&gt;db.users.find({}, { "username" : 1, "email" : 1 })&lt;/td&gt;
&lt;td&gt;SELECT username, email FROM users;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;范围检索&lt;/td&gt;
&lt;td&gt;db.users.find({"age" : { "$gte" : 18, "$lte" : 30 }})   $lt, $lte, $gt, $gte 分别对应 &amp;lt;, &amp;lt;=, &amp;gt;, &amp;gt;=&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE age &amp;gt;= 18 AND age &amp;lt;=30;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;不匹配检索&lt;/td&gt;
&lt;td&gt;db.users.find({ "username" : { "$ne" : "joe" } })&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE username &amp;lt;&amp;gt; 'joe';&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IN 操作符&lt;/td&gt;
&lt;td&gt;db.raffle.find({ "ticket_no" : { "$in" : [725, 542, 390] } })    $in 非常灵活，可以指定不同类型 的条件和值。例如在逐步将用户的 ID 号迁移成用户名的过程中，查询时需要同时匹配 ID 和用户名&lt;/td&gt;
&lt;td&gt;SELECT ticket_no FROM raffles WHERE ticket_no IN (725, 542, 390);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NOT IN 操作符&lt;/td&gt;
&lt;td&gt;db.raffle.find({ "ticket_no" : { "$nin" : [725, 542, 390] } })&lt;/td&gt;
&lt;td&gt;SELECT * FROM raffles WHERE ticket_no not in (725, 542, 390);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OR 操作符&lt;/td&gt;
&lt;td&gt;db.raffle.find({ "$or" : [{ "ticket_no" : 725 }, { "winner" : true }] })&lt;/td&gt;
&lt;td&gt;SELECT * FROM raffles WHERE ticket_no = 725 OR winner = 'true';&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空值检查&lt;/td&gt;
&lt;td&gt;db.c.find({"y" : null}) null 不仅会匹配某个键的值为 null 的文档，而且还会匹配不包含这个键的文档。所以，这种匹配还会返回缺少这个键的所有文档。如果 仅想要匹配键值为 null 的文档，既要检查改建的值是否为 null,   还要通过 $exists 条件 判定键值已经存在   db.c.find({ "z" : { "$in" : [null], "$exists" : true }})&lt;/td&gt;
&lt;td&gt;SELECT * FROM cs WHERE z is null;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多列排序&lt;/td&gt;
&lt;td&gt;db.c.find().sort({ username : 1, age: -1 })&lt;/td&gt;
&lt;td&gt;SELECT * FROM cs ORDER BY username ASC, age DESC;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AND 操作符&lt;/td&gt;
&lt;td&gt;db.users.find({ "$and" : [{ "x" : { "$lt" : 1 }, { "x" : 4 } }] })   由于查询优化器不会对 $and 进行优化，所以可以改写成下面的 db.users.find({ "x" : { "$lt" : 1, "$in" : [4] } })&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE x &amp;gt; 1 AND x IN (4);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NOT 操作符&lt;/td&gt;
&lt;td&gt;db.users.find({ "id_num" : { "$not" : { "$mod" : [5,1] } } })&lt;/td&gt;
&lt;td&gt;SELECT * FROM users WHERE id_num NOT IN (5,1);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LIKE 操作符 (正则匹配)&lt;/td&gt;
&lt;td&gt;db.blogs.find( {  "title" : /post?/i } )    MongoDB 使用 Perl 兼容的正则表达式 (PCRE) 库来匹配正则表达式，任何 PCRE 支持表达式的正则表达式语法都能被 MongoDB 接受&lt;/td&gt;
&lt;td&gt;SELECT * FROM blogs WHERE title LIKE "post%";&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="五、 函数对比"&gt;五、函数对比&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2 }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1 }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5 }
{ "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10 }
{ "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10 }
&lt;/code&gt;&lt;/pre&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;函数对比&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;COUNT&lt;/td&gt;
&lt;td&gt;db.foo.count()&lt;/td&gt;
&lt;td&gt;SELECT COUNT(id) FROM foo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DISTINCT&lt;/td&gt;
&lt;td&gt;db.runCommand({ "distinct": "people", "key": "age" })&lt;/td&gt;
&lt;td&gt;SELECT DISTINCT(age) FROM people;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MIN&lt;/td&gt;
&lt;td&gt;db.sales.aggregate( [ { $group: { _id: {}, minQuantity: { $min: "$quantity" } } } ]);     结果： { "_id" : {  }, "minQuantity" : 1 }&lt;/td&gt;
&lt;td&gt;SELECT MIN(quantity) FROM sales;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MAX&lt;/td&gt;
&lt;td&gt;db.sales.aggregate( [ { $group: { _id: {}, maxQuantity: { $max: "$quantity" } } } ]);&lt;/td&gt;
&lt;td&gt;SELECT MAX(quantity) FROM sales;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVG&lt;/td&gt;
&lt;td&gt;db.sales.aggregate( [ { $group: { _id: {}, avgQuantity: { $avg: "$quantity" } } } ]);&lt;/td&gt;
&lt;td&gt;SELECT AVG(quantity) FROM sales;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUM&lt;/td&gt;
&lt;td&gt;db.sales.aggregate( [ { $group: { _id: {}, totalPrice: { $sum: "$price" } } } ]);&lt;/td&gt;
&lt;td&gt;SELECT SUM(price) FROM sales;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="六、 CURD 对比"&gt;六、CURD 对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;CURD 对比&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;插入数据&lt;/td&gt;
&lt;td&gt;post = {"title" : "My Blog Post", "content" : "Here`s my blog post"}; db.blog.insert(post) 如果 blog 这个集合不存在，则会创建&lt;/td&gt;
&lt;td&gt;INSERT INTO blogs(&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;blog_content&lt;/code&gt;) VALUES ('My Blog Post', 'Here`s my blog post.')&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;批量插入&lt;/td&gt;
&lt;td&gt;db.blog.batchInsert([{ "title" : "AAA", "content" : "AAA---" }, { "title" : "BBB", "content" : "JJJJ--" }])   当前版本的 MongoDB 能接受最大消息长度 48MB，所以在一次批量插入中能插入的文档是有限制的。并且在执行批量插入的过程中，有一个文档插入失败，那么在这个文档之前的所有文档都会成功插入到集合中，而这个文档以及之后的所有文档全部插入失败。&lt;/td&gt;
&lt;td&gt;INSERT INTO blogs(&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;blog_content&lt;/code&gt;) VALUES('AAA', 'AAA---'), ('BBB', 'BBB---');&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查询数据&lt;/td&gt;
&lt;td&gt;db.blog.find(); db.blog.findOne();&lt;/td&gt;
&lt;td&gt;SELECT * FROM blogs;   SELECT * FROM blogs LIMIT 1;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;更新旧数据&lt;/td&gt;
&lt;td&gt;post.blog_content = "十一";   db.blog.update({title: "My Blog Post"}, post)&lt;/td&gt;
&lt;td&gt;UPDATE set blog_content = "十一" WHERE title = "My Blog Post";&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;更新新增 COLUMN&lt;/td&gt;
&lt;td&gt;post.comments = "very good";   db.blog.update({title : "My Blog Post"}, post)&lt;/td&gt;
&lt;td&gt;ALTER table &lt;code&gt;blogs&lt;/code&gt; ADD COLUMN comments varchar(200);   UPDATE &lt;code&gt;blogs&lt;/code&gt; set comments = "very good" WHERE title = 'My Blog Post';&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;删除数据&lt;/td&gt;
&lt;td&gt;db.blog.remove({ title : "My Blog Post" })&lt;/td&gt;
&lt;td&gt;DELETE FROM &lt;code&gt;blogs&lt;/code&gt; WHERE title = 'My Blog Post'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;校验&lt;/td&gt;
&lt;td&gt;post.blog_visit = 123;    db.blog.update({title : "My Blog Post"}, post);   post.blog_visit = "asd.123aaa";    db.blog.update({title : "My Blog Post"}, post)    插入的时候，检查大小。所有的文档都必须小于 16MB。这样做的目的是为了防止不良的模式设计，并且保持性能一直。由于 MongoDB 只进行最基本的检查，所以插入非法的数据很容易。&lt;/td&gt;
&lt;td&gt;类型校验，长度校验。ALTER table &lt;code&gt;blogs&lt;/code&gt; ADD COLUMN blog_visit INT(10);    UPDATE blogs SET blog_visit = "asdasd" WHERE id = 1;   ERROR 1366 (HY000): Incorrect integer value: 'asdasd' for column 'blog_visit' at row 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;删除表&lt;/td&gt;
&lt;td&gt;db.blog.remove({}), db.blog.drop()&lt;/td&gt;
&lt;td&gt;DELETE from blogs; drop table blogs;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="七、有的没的"&gt;七、有的没的&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MongoDB:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GridFS&lt;/p&gt;

&lt;p&gt;可以用来存储大文件 (&amp;gt;16M), 与 MySQL BLOB，TEXT 类似。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MapReduce&lt;/p&gt;

&lt;p&gt;MapReduce
是一种计算模型，简单的说就是将大批量的工作数据分解执行，然后再将结果合并成
最终结果。MongoDB 提供的 MapReduce
非常灵活，对于大规模数据分析也相当实用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;时间有限的集合&lt;/p&gt;

&lt;p&gt;MongoDB 2.2 引入一个新特性--
TTL 集合，TTL 集合支持失效时间设置，使用 expireAfterSeconds 来实现
当超过指定时间后，集合自动清除超时的文档，这用来保存一些诸如 session 会话信息
的时候非常有用，或者存储数据使用。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jianshu.com/p/b0e51059e773" rel="nofollow" target="_blank" title=""&gt;戳这里&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;无 JOIN&lt;/p&gt;

&lt;p&gt;MongoDB 为了更快的读，以及更方便的分布式，抛弃了 JOIN 操作。
JOIN 开销其实很大。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于锁&lt;/p&gt;

&lt;p&gt;当资源被代码的多个部分所共享时，需要确定这处资源只能在一个地方被操作。
就版本的 MongoDB(pre
2.0) 拥有一个全局的写入锁。这就意味着贯穿整个服务器只有一个地方做写操作。
这就可能导致数据库因为某个地方锁定超负载而停滞。这个问题在 2.0 版本中得到
了显著的改善，并且在 2.2 版本中得到了进一步的加强。MongoDB
2.2 使用数据库级别的锁再这个问题上迈进了一大步。&lt;/p&gt;

&lt;p&gt;图中是两个不同版本的 MongoDB，写入性能对比。
&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/mongo_suo.jpeg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.csdn.net/lantian0802/article/details/43505339" rel="nofollow" target="_blank" title=""&gt;戳这里&lt;/a&gt;
&lt;a href="http://blog.csdn.net/lantian0802/article/details/43449677" rel="nofollow" target="_blank" title=""&gt;戳这里&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MySQL InnoDB 使用行级锁，有效提高并发。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;无事务&lt;/p&gt;

&lt;p&gt;不像 MySQL
这些多行数据原子操作的传统数据库。MongoDB 只支持单个文件的原子修改。
但这也正是 MongoDB 可以更快地读的原因，没有事务这些负载的处理。MongoDB
可以轻松处理 TB 级别的数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;磁盘消耗&lt;/p&gt;

&lt;p&gt;MongoDB
会消耗太多的磁盘空间了。当然，这与它的编码方式有关，因为 MongoDB 会通过预分配
大文件空间来避免磁盘碎片问题。它的工作方式是这样：在创建数据库时，系统会创建
一个名为 [db_name].0 的文件，当该文件有一半以上被使用时，系统会再次创建一个名
为 [db_namel].1 的文件，该文件的大小是方才的两倍。这个情况会持续不断的发生，因此
256、512、1024、2048 大小的文件会被写到磁盘上。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MySQL:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;强大的引擎&lt;/p&gt;

&lt;p&gt;InnoDB 引擎：MySQL 默认的事务性引擎。它被设计用来处理大量的短期事务，短期
事务大部分情况是正常提交的，很少会被回滚。InnoDB 采用 MVCC 来支持高并发。&lt;/p&gt;

&lt;p&gt;MyISAM 引擎：5.1 以及之前的默认版本。全文索引，压缩，空间函数，但是 MyISAM 不支持事务和
行级锁。MyISAM 最整张表加锁，而不是针对行。读取时会对需要读到的所有表加
共享锁，写入时则对表加排它锁。&lt;/p&gt;

&lt;p&gt;Memory 引擎：比 MyISAM 表块一个数量级，因为所有的数据都保存在内存中，不需要进行磁盘 I/O。数据会丢失&lt;/p&gt;

&lt;p&gt;Infobright 是最有名的面向列的存储引擎。但该引擎不支持索引。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;事务&lt;/p&gt;

&lt;p&gt;确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中&lt;/p&gt;

&lt;p&gt;的数据应满足完整性约束。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;schema&lt;/p&gt;

&lt;p&gt;有利于数据整理，数据存储，并执行正规化的行为。保证数据的完整性，一致性。&lt;/p&gt;

&lt;p&gt;描述了数据存储的模板，比如创建 table。&lt;/p&gt;

&lt;p&gt;校验数据的格式，比如整形的 column 就不能存放字符串数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="八、 MySQL 与 MongoDB 写入对比"&gt;八、MySQL 与 MongoDB 写入对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;options&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time taken for tests:&lt;/td&gt;
&lt;td&gt;548.281 seconds&lt;/td&gt;
&lt;td&gt;661.318 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total transferred:&lt;/td&gt;
&lt;td&gt;44000000 bytes&lt;/td&gt;
&lt;td&gt;44200000 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests per second:&lt;/td&gt;
&lt;td&gt;182.39 [#/sec]&lt;/td&gt;
&lt;td&gt;151.21 [#/sec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per request:&lt;/td&gt;
&lt;td&gt;274.141 [ms]&lt;/td&gt;
&lt;td&gt;330.659 [ms]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per request(across all concurrent requests):&lt;/td&gt;
&lt;td&gt;5.483 [ms]&lt;/td&gt;
&lt;td&gt;6.613 [ms]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transfer rate:&lt;/td&gt;
&lt;td&gt;78.37 [Kbytes/sec] received&lt;/td&gt;
&lt;td&gt;65.27 [Kbytes/sec] received&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;在本测试例子中，MySQL 写入情况好于 MongoDB&lt;/p&gt;

&lt;p&gt;压测参考命令：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ab -c 50 -n 100000 http://127.0.0.1:6666/deals/mysql_write
ab -c 50 -n 100000 http://127.0.0.1:6666/deals/mongodb_write
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="九、 MySQL 与 MongoDB 读取对比"&gt;九、MySQL 与 MongoDB 读取对比&lt;/h2&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;options&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time taken for tests:&lt;/td&gt;
&lt;td&gt;1181.881 seconds&lt;/td&gt;
&lt;td&gt;606.406 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed requests:&lt;/td&gt;
&lt;td&gt;2239&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-2xx responses:&lt;/td&gt;
&lt;td&gt;2239&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total transferred:&lt;/td&gt;
&lt;td&gt;359397490 bytes&lt;/td&gt;
&lt;td&gt;44100000 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests per second:&lt;/td&gt;
&lt;td&gt;84.61 [#/sec]&lt;/td&gt;
&lt;td&gt;164.91 [#/sec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per request:&lt;/td&gt;
&lt;td&gt;590.941 [ms]&lt;/td&gt;
&lt;td&gt;303.203 [ms]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per request(across all concurrent requests):&lt;/td&gt;
&lt;td&gt;11.819 [ms]&lt;/td&gt;
&lt;td&gt;6.064 [ms]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transfer rate:&lt;/td&gt;
&lt;td&gt;296.96 [Kbytes/sec] received&lt;/td&gt;
&lt;td&gt;71.02 [Kbytes/sec] received&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;在本测试例子中，MySQL 读取性能没有 MongoDB 好&lt;/p&gt;

&lt;p&gt;压测参考命令：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ab -c 50 -n 100000 http://127.0.0.1:6666/deals/mysql_read
ab -c 50 -n 100000 http://127.0.0.1:6666/deals/mongodb_read
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.cppblog.com/wolf/articles/69089.html" rel="nofollow" target="_blank" title=""&gt;MySQL 外键使用&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://mongodbcanred.blogspot.co.id/2015/01/mongodb.html" rel="nofollow" target="_blank" title=""&gt;MongoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.csdn.net/article/2012-11-15/2811920-mongodb-quan-gong-lue" rel="nofollow" target="_blank" title=""&gt;MongoDB 核心贡献者：不是 MongoDB 不行，而是你不懂！&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.csdn.net/cntway/article/details/8257811" rel="nofollow" target="_blank" title=""&gt;MongoDB 和 MySQL 性能测试及其结果分析&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/topics/13870" title=""&gt;Apache Benchmark 的使用的个人浅薄经验&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 13 Oct 2015 17:51:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/27659</link>
      <guid>https://ruby-china.org/topics/27659</guid>
    </item>
    <item>
      <title>MySQL 你以为你以为的就是你以为的？</title>
      <description>&lt;h4 id="一、InnoDB在任何情况下都是按主键正序排列的么？"&gt;一、InnoDB 在任何情况下都是按主键正序排列的么？&lt;/h4&gt;
&lt;p&gt;很早之前，我无知，以为 InnoDB 中的数据都是按照 id 正序排序的，直到我看到了下面的例子。。。&lt;/p&gt;

&lt;p&gt;索引如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `pay_account_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_id` int(11) NOT NULL DEFAULT '0' ,
  `b_amount` int(11) NOT NULL DEFAULT '0' ,
  `r_amount` int(11) NOT NULL DEFAULT '0' ,
  `amount` int(11) NOT NULL DEFAULT '0' ,
  `log_type` int(11) NOT NULL DEFAULT '0' ,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_created_at` (`created_at`,`id`),
  KEY `idx_account_type` (`account_id`,`log_type`,`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;三个 column 的索引&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 AND (created_at &amp;gt;= '2015-08-23 00:00:00');
+----+-------------+------------------+------+---------------------------------+------------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys                   | key              | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+---------------------------------+------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_created_at,idx_account_type | idx_account_type | 4       | const |    4 | Using where |
+----+-------------+------------------+------+---------------------------------+------------------+---------+-------+------+-------------+
1 row in set (0.01 sec)


mysql&amp;gt; SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408;
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| id      | account_id | b_amount | r_amount | amount   | log_type | created_at          | updated_at          |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| 9999959 |     408 |              0 |             0 |  -210000 |        1 | 2015-08-23 13:18:43 | 2015-08-23 13:18:43 |
| 9999945 |     408 |              0 |             0 | -1000000 |        2 | 2015-08-23 13:14:44 | 2015-08-23 13:14:44 |
| 9999943 |     408 |        1000000 |             0 |  1000000 |        4 | 2015-08-23 13:13:46 | 2015-08-23 13:13:46 |
| 9999955 |     408 |         210000 |             0 |   210000 |        4 | 2015-08-23 13:18:17 | 2015-08-23 13:18:17 |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+

结果并不是按照id正序排列的
account_id 和 log_type 是有序的，但是id并不是有序的。
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 order by id desc;
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
| id | select_type | table            | type | possible_keys              | key                        | key_len | ref   | rows | Extra                       |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id_log_type | idx_of_account_id_log_type | 4       | const |    4 | Using where; Using filesort |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 order by log_type desc, id desc;
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys              | key                        | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id_log_type | idx_of_account_id_log_type | 4       | const |    4 | Using where |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 order by log_type asc, id desc;
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
| id | select_type | table            | type | possible_keys              | key                        | key_len | ref   | rows | Extra                       |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id_log_type | idx_of_account_id_log_type | 4       | const |    4 | Using where; Using filesort |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-----------------------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 order by log_type desc;
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys              | key                        | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id_log_type | idx_of_account_id_log_type | 4       | const |    4 | Using where |
+----+-------------+------------------+------+----------------------------+----------------------------+---------+-------+------+-------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据按照 &lt;code&gt;account_id&lt;/code&gt;,&lt;code&gt;log_type&lt;/code&gt;,&lt;code&gt;id&lt;/code&gt; 升序排序&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;两个 column 的情况&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果索引是如下方式创建&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; alter table pay_account_logs add index `idx_of_account_id` (`account_id`, `id`);

mysql&amp;gt; SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408;
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| id      | account_id | b_amount | r_amount | amount   | log_type | created_at          | updated_at          |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| 9999943 |     408 |        1000000 |             0 |  1000000 |        4 | 2015-08-23 13:13:46 | 2015-08-23 13:13:46 |
| 9999945 |     408 |              0 |             0 | -1000000 |        2 | 2015-08-23 13:14:44 | 2015-08-23 13:14:44 |
| 9999955 |     408 |         210000 |             0 |   210000 |        4 | 2015-08-23 13:18:17 | 2015-08-23 13:18:17 |
| 9999959 |     408 |              0 |             0 |  -210000 |        1 | 2015-08-23 13:18:43 | 2015-08-23 13:18:43 |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
4 rows in set (0.00 sec)

mysql&amp;gt; explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408;
+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------+
| id | select_type | table            | type | possible_keys     | key               | key_len | ref   | rows | Extra |
+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id | idx_of_account_id | 4       | const |    4 |       |
+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------+
1 row in set (0.01 sec)

account_id 和 id 是正序排序的。由于索引中没有log_type 所以log_type并不是有序的。

&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408 ORDER BY id desc;

+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys     | key               | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | pay_account_logs | ref  | idx_of_account_id | idx_of_account_id | 4       | const |    4 | Using where |
+----+-------------+------------------+------+-------------------+-------------------+---------+-------+------+-------------+
1 row in set (9.51 sec)

以上情况并没有出现 Using filesort 的情况
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据按照&lt;code&gt;account_id&lt;/code&gt;,&lt;code&gt;id&lt;/code&gt; 升序排列&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;在没有索引的情况&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408;
+----+-------------+------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table            | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | pay_account_logs | ALL  | NULL          | NULL | NULL    | NULL | 1684032 | Using where |
+----+-------------+------------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; SELECT SQL_NO_CACHE `pay_account_logs`.* FROM `pay_account_logs` WHERE `pay_account_logs`.`account_id` = 408;
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| id      | account_id | balance_amount | refund_amount | amount   | log_type | created_at          | updated_at          |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
| 9999943 |     408 |        1000000 |             0 |  1000000 |        4 | 2015-08-23 13:13:46 | 2015-08-23 13:13:46 |
| 9999945 |     408 |              0 |             0 | -1000000 |        2 | 2015-08-23 13:14:44 | 2015-08-23 13:14:44 |
| 9999955 |     408 |         210000 |             0 |   210000 |        4 | 2015-08-23 13:18:17 | 2015-08-23 13:18:17 |
| 9999959 |     408 |              0 |             0 |  -210000 |        1 | 2015-08-23 13:18:43 | 2015-08-23 13:18:43 |
+---------+------------+----------------+---------------+----------+----------+---------------------+---------------------+
4 rows in set (2.47 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据按照主键 id 升序排列。我们以为按照主键升序的情况，都是这个例子。&lt;/p&gt;

&lt;p&gt;查看索引组织数据&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE people(
  last_name varchar(50) not null,
  first_name varchar(50) not null,
  dob  date not null,
  gender enum('m','f') not null,
  key(last_name, first_name, dob)
);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/mysql_index_01.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;从以上例子也可以证明，索引中的数据是有序的。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;联合索引，是依次按照索引顺序，正序排列的。但不能保证所有字段都是正序排列的。&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="二、MySQL 关键字，以及关键字带来的坑"&gt;二、MySQL 关键字，以及关键字带来的坑&lt;/h4&gt;
&lt;p&gt;很早之前，我无知，以为名字可以随便起，直到我看到了下面的例子。&lt;/p&gt;

&lt;p&gt;表结构如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; desc a_authorities;

+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| key        | varchar(100) | NO   | UNI |         |                |
| desc       | varchar(100) | NO   |     |         |                |
| label      | varchar(100) | NO   |     |         |                |
| group      | varchar(100) | NO   |     |         |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (12.89 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;where 条件之后&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
mysql&amp;gt; select * from a_authorities where key = 'manage_roles'\G;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key = 'manage_roles'' at line 1
ERROR: 
No query specified

mysql&amp;gt; select * from a_authorities where `key` = 'manage_roles'\G;
*************************** 1. row ***************************
        id: 2
       key: manage_roles
      desc: 我的权限
     label: 我的权限
     group: 我的权限
created_at: 2014-10-28 11:12:02
updated_at: 2014-10-28 11:12:02
1 row in set (0.01 sec)

ERROR: 
No query specified

mysql&amp;gt; select * from a_authorities where a_authorities.key = 'manage_roles'\G;
*************************** 1. row ***************************
        id: 2
       key: manage_roles
      desc: 我的权限
     label: 我的权限
     group: 我的权限
created_at: 2014-10-28 11:12:02
updated_at: 2014-10-28 11:12:02
1 row in set (0.40 sec)

ERROR: 
No query specified
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;select 之后&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select desc from a_authorities where id = 2\G;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'desc from a_authorities where id = 2' at line 1
ERROR: 
No query specified

mysql&amp;gt; select `desc` from a_authorities where id = 2\G;
*************************** 1. row ***************************
desc: 我的权限
1 row in set (0.00 sec)

ERROR: 
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;分组&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
mysql&amp;gt; select count(id), group from a_authorities group by group;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group from a_authorities group by group' at line 1


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;以上 column key，desc，label，group 均为关键字&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;关键字在查询，排序，分组等 SQL 语句中都会有异常&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;如果记不住那么多关键字，使用 ad_key，ad_desc，ad_label，ad_group 这种自定义前缀的方式命名 column&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.cnblogs.com/jiangshan5xian/archive/2013/03/16/2963496.html" rel="nofollow" target="_blank" title=""&gt;MySQL 中的关键字&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Fri, 28 Aug 2015 08:50:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/27105</link>
      <guid>https://ruby-china.org/topics/27105</guid>
    </item>
    <item>
      <title>MySQL 联合索引 (a,b) 的一些困惑</title>
      <description>&lt;p&gt;疑问：&lt;/p&gt;

&lt;p&gt;MySQL 建立 (a,b) 的索引，理论上，只有 a, (a,b)  两种情况能用到索引，但是其他情况也能用到索引么？下面就为你一一测试&lt;/p&gt;

&lt;p&gt;数据库版本&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/local/bin/mysql  Ver 14.14 Distrib 5.6.16, for osx10.9 (x86_64) using  EditLine wrapper

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="一、表结构"&gt;一、表结构&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `cd_happy_for_ni_deals` (
  `id` int(11) NOT NULL DEFAULT '0',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `publish_status` int(11) NOT NULL DEFAULT '4' COMMENT '发布状态',
  KEY `idx_of_publish_status_update_time` (`publish_status`,`update_time`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="二、唯一性基数"&gt;二、唯一性基数&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select count(distinct(update_time)) from cd_happy_for_ni_deals;
+------------------------------+
| count(distinct(update_time)) |
+------------------------------+
|                      1845933 |
+------------------------------+
1 row in set (4.68 sec)

mysql&amp;gt; select count(distinct(publish_status)) from cd_happy_for_ni_deals;
+---------------------------------+
| count(distinct(publish_status)) |
+---------------------------------+
|                               2 |
+---------------------------------+
1 row in set (1.76 sec)

mysql&amp;gt; select count(id) from cd_happy_for_ni_deals;
+-----------+
| count(id) |
+-----------+
|   1907609 |
+-----------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;update_time 的选择性：1845933 / 1907609.to_f =  0.9676684268107353 接近 1&lt;/p&gt;

&lt;p&gt;publish_status 的选择性：2 / 1907609.to_f   =  1.0484328811617055e-06 接近 0&lt;/p&gt;
&lt;h4 id="三、建立(a,b) 索引，分别根据 a 查询，b 查询，(a,b) 查询，(b,a) 查询，统计结果"&gt;三、建立 (a,b) 索引，分别根据 a 查询，b 查询，(a,b) 查询，(b,a) 查询，统计结果&lt;/h4&gt;
&lt;p&gt;不走寻常路，我就偏选择 选择性低的做索引的第一位。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;创建索引&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; alter table cd_happy_for_ni_deals add index `idx_of_publish_status_update_time` (`publish_status`, `update_time`, `id`);
Query OK, 0 rows affected (14.69 sec)
Records: 0  Duplicates: 0  Warnings: 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;根据 a 查询&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain select SQL_NO_CACHE id, publish_status from cd_happy_for_ni_deals where publish_status = 4 \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: cd_happy_for_ni_deals
         type: ref
possible_keys: idx_of_publish_status_update_time
          key: idx_of_publish_status_update_time
      key_len: 4
          ref: const
         rows: 964056 &amp;lt;- 只查询publish_status 的情况
        Extra: Using index
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from cd_happy_for_ni_deals where publish_status = 4 \G;
*************************** 1. row ***************************
count(id): 1858081
1 row in set (0.69 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;理论上可以用到索引 (a,b) 中的 a 部分。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;根据 b 查询&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain select SQL_NO_CACHE id, publish_status from cd_happy_for_ni_deals where update_time = '2014-05-17 23:00:48' \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: cd_happy_for_ni_deals
         type: index
possible_keys: NULL
          key: idx_of_publish_status_update_time
      key_len: 17
          ref: NULL
         rows: 1928113 &amp;lt;- 只查询update_time 的情况
        Extra: Using where; Using index
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from cd_happy_for_ni_deals where update_time = '2014-05-17 23:00:48' \G;
*************************** 1. row ***************************
count(id): 1
1 row in set (1.06 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询 b 的时候，理论上用不到索引的。为啥这里？？？&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;根据 (a,b) 查询&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain select SQL_NO_CACHE id, publish_status from cd_happy_for_ni_deals where publish_status = 4 and update_time = '2014-05-17 23:00:48' \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: cd_happy_for_ni_deals
         type: ref
possible_keys: idx_of_publish_status_update_time
          key: idx_of_publish_status_update_time
      key_len: 13
          ref: const,const
         rows: 1
        Extra: Using where; Using index
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from cd_happy_for_ni_deals where publish_status = 4 and update_time = '2014-05-17 23:00:48' \G;
*************************** 1. row ***************************
count(id): 1
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;符合理论上的预期。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;根据 (b,a) 查询&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain select SQL_NO_CACHE id, publish_status from cd_happy_for_ni_deals where  update_time = '2014-05-17 23:00:48' and publish_status = 4 \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: cd_happy_for_ni_deals
         type: ref
possible_keys: idx_of_publish_status_update_time
          key: idx_of_publish_status_update_time
      key_len: 13
          ref: const,const
         rows: 1
        Extra: Using where; Using index
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from cd_happy_for_ni_deals where  update_time = '2014-05-17 23:00:48' and publish_status = 4 \G;
*************************** 1. row ***************************
count(id): 1
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;理论上，这里只能用到（a,b）中的 a 部分，为啥也这么快？？&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;欢迎群里的小伙伴热烈讨论&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;暂时的结论：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1、理论上索引对顺序是敏感的，但是由于 MySQL 的查询优化器会自动调整 where 子句的条件顺序以使用适合的索引。&lt;/p&gt;

&lt;p&gt;2、将选择性高的列放在索引的最前列。根据场景的不同，这条经验法则并不是完全准确的。在某些场景下，可能需要根据运行频率最高的查询来调整索引列的顺序。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.programering.com/a/MTMwAzMwATM.html" rel="nofollow" target="_blank" title=""&gt;http://www.programering.com/a/MTMwAzMwATM.html&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Fri, 21 Aug 2015 16:36:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/27022</link>
      <guid>https://ruby-china.org/topics/27022</guid>
    </item>
    <item>
      <title>MySQL 慢查询的特征表现及优化方式</title>
      <description>&lt;p&gt;&lt;strong&gt;我们将超过指定时间的 SQL 语句查询称为慢查询&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="一、慢查询的体现"&gt;一、慢查询的体现&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;慢查询主要体现在&lt;strong&gt;慢&lt;/strong&gt;上，通常意义上来讲，只要返回时间大于 &lt;strong&gt;&amp;gt;1 sec&lt;/strong&gt;上的查询都可以称为慢查询。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;慢查询会导致 CPU，内存消耗过高。数据库服务器压力陡然过大，那么大部分情况来讲，肯定是由某些慢查询导致的。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;查看/设置“慢查询”的时间定义&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; show variables like "long%";
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 0.000100 |
+-----------------+----------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如上述语句输出，“慢查询”的时间定义为 0.0001 秒（方便测试，一般设置为 1-10 秒）。使用下面语句定义“慢查询”时间&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; set long_query_time=0.0001;
Query OK, 0 rows affected (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;开启“慢查询”记录功能&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; show variables like "slow%";
+---------------------+------------------------------------+
| Variable_name       | Value                              |
+---------------------+------------------------------------+
| slow_launch_time    | 2                                  |
| slow_query_log      | OFF                                |
| slow_query_log_file | /opt/mysql/data/localhost-slow.log |
+---------------------+------------------------------------+
3 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述语句查看“慢查询”的配置信息，你可以自定义日志文件的存放，但必须将 slow_query_log 全局变量设置为“ON”状态，执行以下语句&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; set global slow_query_log=ON;
Query OK, 0 rows affected (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; show variables like "slow%";
+---------------------+------------------------------------+
| Variable_name       | Value                              |
+---------------------+------------------------------------+
| slow_launch_time    | 2                                  |
| slow_query_log      | ON                                 |
| slow_query_log_file | /opt/mysql/data/localhost-slow.log |
+---------------------+------------------------------------+
3 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么哪些条件可以导致慢查询呢？或者说根据何种条件判断，优化慢查询。仅从 SQL 语句方面阐述慢查询，MySQL 系统级别的设置暂不考虑。&lt;/p&gt;
&lt;h4 id="二、返回列数太多"&gt;二、返回列数太多&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;返回列数太多&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT `happy_ni_nis`.*
FROM `happy_ni_nis`
ORDER BY n_total DESC LIMIT 10\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_ni_nis
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 66493186  &amp;lt;- 返回值太多，坏味道
        Extra: Using filesort &amp;lt;- 避免使用排序
1 row in set (0.01 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优化建议：添加 关于 n_total 的索引&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; alter table happy_ni_nis add index `idx_of_n_total` (`n_total`, `id`);
Query OK, 0 rows affected (7 min 48.27 sec)
Records: 0  Duplicates: 0  Warnings: 0


EXPLAIN SELECT `happy_ni_nis`.*
FROM `happy_ni_nis`
ORDER BY n_total DESC LIMIT 10\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_ni_nis
         type: index
possible_keys: NULL
          key: idx_of_n_total
      key_len: 8
          ref: NULL
         rows: 10
        Extra: 
1 row in set (0.01 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;但是某些情况下，返回列数比较多，也不代表是慢查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT `cd_happys`.*
FROM `cd_happys`
WHERE `cd_happys`.`p_status` = 4
  AND `cd_happys`.`status` IN (0,
                                     1,
                                     2,
                                     3,
                                     4)
  AND (c_time &amp;lt;= '2015-05-15 23:30:39'
       AND update_time &amp;lt;= '2015-05-15 23:30:39')
ORDER BY `cd_happys`.`id` ASC LIMIT 1000

+----+-------------+-----------------+-------+---------------------------------------+---------+---------+-----+------+-------------+
| id | select_type | table           | type  | possible_keys                         | key     | key_len | ref | rows | Extra       |
+----+-------------+-----------------+-------+---------------------------------------+---------+---------+-----+------+-------------+
| 1  | SIMPLE      | cd_happys | index | idx_uptime_seneditor,idx_c_time | PRIMARY | 4       |     | 2000 | Using where |
+----+-------------+-----------------+-------+---------------------------------------+---------+---------+-----+------+-------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：6 sec&lt;/p&gt;

&lt;p&gt;添加一个 `&lt;code&gt;idx_of_p_status_status_c_time&lt;/code&gt; (&lt;code&gt;p_status&lt;/code&gt;,&lt;code&gt;status&lt;/code&gt;,&lt;code&gt;c_time&lt;/code&gt;,&lt;code&gt;id&lt;/code&gt;)` 索引&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain SELECT SQL_NO_CACHE  `cd_happys`.* FROM `cd_happys`  WHERE `cd_happys`.`p_status` = 4 AND `cd_happys`.`status` IN (0, 1, 2, 3, 4) AND (c_time &amp;lt;= '2015-05-15 23:30:39' and update_time &amp;lt;= '2015-05-15 23:30:39')  LIMIT 1000\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: cd_happys
         type: range
possible_keys: idx_uptime_seneditor,idx_c_time,idx_of_p_status_sanzu_check_status_signup_status,idx_of_p_status_status_c_time
          key: idx_of_p_status_status_c_time
      key_len: 16
          ref: NULL
         rows: 3782
        Extra: Using where
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.4 sec&lt;/p&gt;
&lt;h4 id="三、分页条件，过大的offset"&gt;三、分页条件，过大的 offset&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT `happys`.*
FROM `happys`
INNER JOIN `happy_infos` ON `happy_infos`.`happy_id` = `happys`.`id`
WHERE
  (happys.end_time &amp;gt; '2015-08-13 14:08:10')
  AND (happys.j_tag_id &amp;gt; 0)
  AND (happy_infos.my_image_url = '')
ORDER BY happys.updated_at DESC LIMIT 100
OFFSET 28900\G;


+----+-------------+------------+--------+------------------------------------------------------------+---------------+---------+-----------------+--------+-----------------------------+
| id | select_type | table      | type   | possible_keys                                              | key           | key_len | ref             | rows   | Extra                       |
+----+-------------+------------+--------+------------------------------------------------------------+---------------+---------+-----------------+--------+-----------------------------+
| 1  | SIMPLE      | happys      | range  | PRIMARY,idx_end_time,idx_bg_tag_pub_beg,idx_bg_tag_pub_end | idx_end_time  | 8       |                 | 219114 | Using where; Using filesort |
+----+-------------+------------+--------+------------------------------------------------------------+---------------+---------+-----------------+--------+-----------------------------+
| 1  | SIMPLE      | happy_infos | eq_ref | happy_id_index                                              | happy_id_index | 4       | tao800.happys.id | 1      | Using where                 |
+----+-------------+------------+--------+------------------------------------------------------------+---------------+---------+-----------------+--------+-----------------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：&lt;/p&gt;

&lt;p&gt;Empty set (9.78 sec)&lt;/p&gt;

&lt;p&gt;优化建议：  &lt;/p&gt;

&lt;p&gt;1、MySQL 里对 LIMIT OFFSET 的处理方式是，取出 OFFSET+LIMIT 的所有数据，然后去掉 OFFSET，返回底部的 LIMIT
  使用子查询，使用覆盖索引进行优化。&lt;/p&gt;

&lt;p&gt;2、这种方式在 offset 很高的情况下，
  如：limit 100000,20，这样系统会查询 100020 条，然后把前面的 100000 条都扔掉，这是开销很大的操作，导致慢查询很慢。&lt;/p&gt;

&lt;p&gt;3、使用覆盖索引 (convering index) 查询，然后再跟全行做 join 操作。这样可以直接使用 index 得到数据，而不是去查询表，
     当找到需要的数据之后，再与全表 join 获得其他列。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT SQL_NO_CACHE `happys`.*
FROM `happys`
INNER JOIN
(
SELECT happys.id
FROM happys
INNER JOIN `happy_infos` ON `happy_infos`.`happy_id` = `happys`.`id`
WHERE happys.end_time &amp;gt; '2015-08-13 14:08:10'
      AND happys.j_tag_id &amp;gt; 0
      AND happy_infos.my_image_url = ''
LIMIT 100 OFFSET 28900
) AS lim ON lim.id = happys.id
ORDER BY happys.updated_at DESC \G;

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Impossible WHERE noticed after reading const tables
*************************** 2. row ***************************
           id: 2
  select_type: DERIVED
        table: happys
         type: range
possible_keys: PRIMARY,idx_end_time,idx_bg_tag_pub_beg,idx_bg_tag_pub_end
          key: idx_bg_tag_pub_end
      key_len: 4
          ref: NULL
         rows: 425143
        Extra: Using where; Using index
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: happy_infos
         type: eq_ref
possible_keys: happy_id_index
          key: happy_id_index
      key_len: 4
          ref: tao800.happys.id
         rows: 1
        Extra: Using where
3 rows in set (0.67 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.67 sec&lt;/p&gt;

&lt;p&gt;&lt;a href="http://zhidao.baidu.com/link?url=4hVpi7DCSX6bEROu33YQD_Gq2IhERaqOl7yyPASjtixIaRbYhCFEteP4KyJX52RI7QxY0mV_6UM2g8p3KeG4BzJx1z94EozoKW-yewhCDju" rel="nofollow" target="_blank" title=""&gt;http://zhidao.baidu.com/link?url=4hVpi7DCSX6bEROu33YQD_Gq2IhERaqOl7yyPASjtixIaRbYhCFEteP4KyJX52RI7QxY0mV_6UM2g8p3KeG4BzJx1z94EozoKW-yewhCDju&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jb51.net/article/27504.htm" rel="nofollow" target="_blank" title=""&gt;http://www.jb51.net/article/27504.htm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jb51.net/article/33777.htm" rel="nofollow" target="_blank" title=""&gt;http://www.jb51.net/article/33777.htm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://chinahnzhou.iteye.com/blog/1567537" rel="nofollow" target="_blank" title=""&gt;http://chinahnzhou.iteye.com/blog/1567537&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://dataunion.org/14895.html" rel="nofollow" target="_blank" title=""&gt;http://dataunion.org/14895.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.idaohang123.com/archives/399" rel="nofollow" target="_blank" title=""&gt;http://blog.idaohang123.com/archives/399&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jbxue.com/db/22798.html" rel="nofollow" target="_blank" title=""&gt;http://www.jbxue.com/db/22798.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.admin10000.com/document/4797.html" rel="nofollow" target="_blank" title=""&gt;http://www.admin10000.com/document/4797.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.fienda.com/archives/110" rel="nofollow" target="_blank" title=""&gt;http://www.fienda.com/archives/110&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down" rel="nofollow" target="_blank" title=""&gt;http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="四、驱动表，临时表，排序"&gt;四、驱动表，临时表，排序&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; EXPLAIN SELECT `happy_d_sales`.`happy_id`
    -&amp;gt; FROM `happy_d_sales`
    -&amp;gt; INNER JOIN happys ON happys.id = happy_d_sales.happy_id
    -&amp;gt; AND happys.j_tag_id = happy_d_sales.tag_id
    -&amp;gt; WHERE (status = 1
    -&amp;gt;        AND date = '2015-08-12')
    -&amp;gt; ORDER BY sales DESC LIMIT 300\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happys
         type: index
possible_keys: PRIMARY,idx_bg_tag_pub_beg,idx_bg_tag_pub_end
          key: idx_bg_tag_pub_beg
      key_len: 20
          ref: NULL
         rows: 850279 &amp;lt;- 返回数据太多，坏味道
        Extra: Using index; Using temporary; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_d_sales
         type: eq_ref
possible_keys: happy_id_date_tag_idx,tag_id_date
          key: happy_id_date_tag_idx
      key_len: 11
          ref: tao800.happys.id,const,tao800.happys.j_tag_id
         rows: 1
        Extra: Using where
2 rows in set (0.00 sec)

ERROR:
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间  Empty set (3.90 sec)&lt;/p&gt;

&lt;p&gt;EXPLAIN 返回的第一列的表，就是驱动表，在驱动表上排序，非常快。但是如果在非驱动表上，排序，就很慢。
默认情况下，记录就是按照顺序排列好的，不需要进行排序。但是上述结果，从&lt;code&gt;happys&lt;/code&gt; 表中取出一些数据，建立临时表，并且还在临时表上进行排序。
所以就会出现 &lt;strong&gt;Using temporary; Using filesort&lt;/strong&gt; 这种情况。&lt;/p&gt;

&lt;p&gt;优化建议：&lt;/p&gt;

&lt;p&gt;1、减少返回值 rows&lt;/p&gt;

&lt;p&gt;2、指定正确的驱动表&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; ALTER table `happy_d_sales` ADD INDEX `idx_of_date_and_status` (`date`, `status`, `sales`, `id`);
Query OK, 0 rows affected (19.45 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&amp;gt; EXPLAIN SELECT `happy_d_sales`.`happy_id`
    -&amp;gt; FROM `happy_d_sales`
    -&amp;gt; STRAIGHT_JOIN happys ON happys.id = happy_d_sales.happy_id
    -&amp;gt; AND happys.j_tag_id = happy_d_sales.tag_id
    -&amp;gt; WHERE  date = '2015-08-12' AND status = 1
    -&amp;gt; ORDER BY `happy_d_sales`.sales DESC LIMIT 300\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_d_sales  &amp;lt;-- 正确的驱动表
         type: ref
possible_keys: happy_id_date_tag_idx,tag_id_date,idx_of_date_and_status
          key: idx_of_date_and_status
      key_len: 7
          ref: const,const
         rows: 1
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happys
         type: eq_ref
possible_keys: PRIMARY,idx_bg_tag_pub_beg,idx_bg_tag_pub_end
          key: PRIMARY
      key_len: 4
          ref: tao800.happy_d_sales.happy_id
         rows: 1
        Extra: Using where
2 rows in set (0.01 sec)

ERROR:
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.03 sec&lt;/p&gt;
&lt;h4 id="五、不合适的group by 分组条件"&gt;五、不合适的 group by 分组条件&lt;/h4&gt;
&lt;p&gt;大表上的 group by&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `p_acc_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_id` int(11) NOT NULL DEFAULT '0' ,
  `b_amount` int(11) NOT NULL DEFAULT '0' ,
  `r_amount` int(11) NOT NULL DEFAULT '0' ,
  `amount` int(11) NOT NULL DEFAULT '0' ,
  `l_type` int(11) NOT NULL DEFAULT '0',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_created_at` (`created_at`,`id`),
  KEY `idx_account_type` (`account_id`,`l_type`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3212639 DEFAULT CHARSET=utf8;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该表上有百万条的数据，也有 关于 &lt;code&gt;account_id&lt;/code&gt; 的索引，但是使用 group by 查询时，确实很慢。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT MAX(id) max_id FROM `p_acc_logs`  WHERE (created_at &amp;lt;= '2015-08-14 00:00:00') GROUP BY account_id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间 10sec&lt;/p&gt;
&lt;h4 id="六、不合适的order by"&gt;六、不合适的 order by&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT SQL_NO_CACHE id,
       u_id,
       amount
FROM `t_orders`
WHERE (settlement_time &amp;gt;= '2015-07-01 00:00:00'
       AND settlement_time &amp;lt;= '2015-09-30 23:59:59')
ORDER BY `t_orders`.`id` ASC LIMIT 3000;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t_orders
         type: index
possible_keys: idx_settlement_time
          key: PRIMARY  &amp;lt;--- 注意这里
      key_len: 4
          ref: NULL
         rows: 6705   &amp;lt;---- 注意这里
        Extra: Using where
1 row in set (0.09 sec)

ERROR:
No query specified
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：40 sec&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `t_orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `u_id` int(11) NOT NULL DEFAULT '0' ,
  `order_id` varchar(20) NOT NULL DEFAULT '' ,
  `amount` int(11) NOT NULL DEFAULT '0' ,
  `settlement_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' ,
  `d_s_time` datetime DEFAULT '1970-01-01 00:00:00' ,
  `serial_number` bigint(20) unsigned DEFAULT NULL ,
  `order_type` int(11) DEFAULT NULL ,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_t_orders_on_u_id_and_settlement_time_and_id` (`u_id`,`settlement_time`,`id`),
  KEY `index_t_orders_on_order_id_and_order_type_and_id` (`order_id`,`order_type`,`id`),
  KEY `index_t_orders_on_serial_number_and_order_type_and_id` (`serial_number`,`order_type`,`id`),
  KEY `idx_settlement_time` (`settlement_time`,`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优化建议：  &lt;/p&gt;

&lt;p&gt;1、去除错误的 order by 查询，&lt;del&gt;InnoDB 存储引擎中，记录集默认就是按照 id 升序排列的，MyISAM 不能保证。&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;2、使查询语句能够按照正确的方式查询&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT SQL_NO_CACHE id,
       u_id,
       amount
FROM `t_orders`
WHERE (settlement_time &amp;gt;= '2015-07-01 00:00:00'
       AND settlement_time &amp;lt;= '2015-09-30 23:59:59')
LIMIT 3000;


*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t_orders
         type: range
possible_keys: idx_settlement_time
          key: idx_settlement_time &amp;lt;-- 注意这里
      key_len: 8
          ref: NULL
         rows: 12784434 &amp;lt;-- 注意这里
        Extra: Using where
1 row in set (0.00 sec)

ERROR:
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.16 sec&lt;/p&gt;
&lt;h4 id="七、模糊查询"&gt;七、模糊查询&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT `p_d_logs`.*
FROM `p_d_logs`
WHERE (details LIKE '%waiting%'
       AND created_at &amp;lt; '2015-08-09 03:40:35')
  AND (`p_d_logs`.`id` &amp;gt; 297273949)
ORDER BY `p_d_logs`.`id` ASC LIMIT 10000\G

+----+-------------+-------------------+-------+---------------+---------+---------+-----+---------+-------------+
| id | select_type | table             | type  | possible_keys | key     | key_len | ref | rows    | Extra       |
+----+-------------+-------------------+-------+---------------+---------+---------+-----+---------+-------------+
| 1  | SIMPLE      | p_d_logs | range | PRIMARY       | PRIMARY | 4       |     | 3340552 | Using where |
+----+-------------+-------------------+-------+---------------+---------+---------+-----+---------+-------------+

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：7.5889787673950195    sec&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT `e_logs`.`loggable_id`
FROM `e_logs`
WHERE (user_name LIKE '%王大傻%'
       AND action_type_id = 0
       AND loggable_type = 'HappyBase') \G;


*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: e_logs
         type: ref
possible_keys: by_loggable_type
          key: by_loggable_type
      key_len: 92
          ref: const
         rows: 684252
        Extra: Using where
1 row in set (10.61 sec)

15738 rows in set (3 min 45.75 sec)

 CREATE TABLE `e_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `loggable_type` varchar(30) NOT NULL DEFAULT '' ,
  `loggable_id` int(11) NOT NULL DEFAULT '0' ,
  `u_id` int(11) NOT NULL DEFAULT '0' ,
  `user_name` varchar(24) NOT NULL DEFAULT '' ,
  `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' ,
  `execution_type_id` tinyint(4) NOT NULL DEFAULT '0' ,
  `action_type_id` tinyint(4) NOT NULL DEFAULT '0' ,
  `from_url` varchar(200) NOT NULL DEFAULT '' ,
  `updated_changes` longtext ,
  `t_s_id` int(11) NOT NULL DEFAULT '0' ,
  PRIMARY KEY (`id`),
  KEY `index_e_logs_on_loggable_id_and_loggable_type` (`loggable_id`,`loggable_type`),
  KEY `idx_user_name` (`user_name`,`action_type_id`,`id`),
  KEY `index_e_logs_on_create_time` (`create_time`),
  KEY `by_t_s_id` (`t_s_id`,`id`),
  KEY `by_loggable_type` (`loggable_type`,`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8



&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优化建议：&lt;/p&gt;

&lt;p&gt;1、调整查询语句顺序&lt;/p&gt;

&lt;p&gt;2、添加合适的索引。删除旧的索引。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alter table e_logs drop index `by_loggable_type`;
Query OK, 0 rows affected (3 min 12.71 sec)


alter table e_logs add index `idx_of_loggable_type_and_type_id` (`loggable_type`, `action_type_id`, `id`);
Query OK, 0 rows affected (6 min 5.70 sec)



EXPLAIN SELECT SQL_NO_CACHE `e_logs`.`loggable_id`
FROM `e_logs`
WHERE (loggable_type = 'HappyBase' AND action_type_id = 0 AND user_name LIKE '王大傻%') \G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: e_logs
         type: range
possible_keys: idx_user_name,idx_of_loggable_type_and_type_id
          key: idx_user_name
      key_len: 75
          ref: NULL
         rows: 39546
        Extra: Using where
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.13 sec  效率提升 1700 倍&lt;/p&gt;
&lt;h4 id="八、检索条件，没有按照索引列查询"&gt;八、检索条件，没有按照索引列查询&lt;/h4&gt;
&lt;p&gt;索引，中范围查询什么的，是否能使用到索引，详细演示一下&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT  happy_id, sum(sales) as all_sales
FROM `happy_d_sales`
WHERE `happy_d_sales`.`status` = 1
AND `happy_d_sales`.`tag_id` IN (xxx,)
GROUP BY happy_id ORDER BY all_sales desc LIMIT 100 OFFSET 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：20sec&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `happy_d_sales` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `happy_id` int(11) NOT NULL ,
  `tag_id` int(11) NOT NULL ,
  `sales` int(11) NOT NULL DEFAULT '0' ,
  `status` int(11) NOT NULL DEFAULT '0' ,
  `date` date NOT NULL ,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `r_count` int(11) NOT NULL DEFAULT '0' ,
  `a_t_s_count` int(11) NOT NULL DEFAULT '0' ,
  PRIMARY KEY (`id`),
  UNIQUE KEY `happy_id_date_tag_idx` (`happy_id`,`date`,`tag_id`),
  KEY `tag_id_date` (`tag_id`,`date`) ,
  KEY `idx_of_date_and_status` (`date`,`status`,`sales`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;调整下 SQL 语句的顺序，并且添加合适的索引，瞬间减少查询时间。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT SQL_NO_CACHE  happy_id, sum(sales) as all_sales
FROM `happy_d_sales`
WHERE `happy_d_sales`.`tag_id` IN (xxxx,xxxx,xxxx)
AND `happy_d_sales`.`status` = 1
GROUP BY happy_id ORDER BY all_sales desc
LIMIT 100 OFFSET 0\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_d_sales
         type: range
possible_keys: tag_id_date,idx_of_tag_id_status_happy_id
          key: idx_of_tag_id_status_happy_id
      key_len: 8
          ref: NULL
         rows: 94380
        Extra: Using where; Using temporary; Using filesort
1 row in set (0.06 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：100 rows in set (0.43 sec)&lt;/p&gt;
&lt;h4 id="九、根本没有索引"&gt;九、根本没有索引&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain select t_s_id from guang_happy_outs group by t_s_id;
+----+-------------+-----------------+------+---------------+------+---------+------+----------+---------------------------------+
| id | select_type | table           | type | possible_keys | key  | key_len | ref  | rows     | Extra                           |
+----+-------------+-----------------+------+---------------+------+---------+------+----------+---------------------------------+
|  1 | SIMPLE      | guang_happy_outs | ALL  | NULL          | NULL | NULL    | NULL | 69008793 | Using temporary; Using filesort |
+----+-------------+-----------------+------+---------------+------+---------+------+----------+---------------------------------+
1 row in set (0.00 sec)

查询时间：3 sec

CREATE TABLE `guang_happy_outs` (
  `id` int(11) NOT NULL AUTO_INCREMENT ,
  `t_s_id` int(11) NOT NULL DEFAULT '0' ,
  `happy_id` int(11) NOT NULL DEFAULT '0' ,
  `count` int(11) NOT NULL DEFAULT '0' ,
  `de_id` int(11) NOT NULL DEFAULT '0' ,
  `ad_count` int(11) NOT NULL DEFAULT '0' ,
  `st_date` date NOT NULL DEFAULT '1970-01-01' ,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `amount` int(11) NOT NULL DEFAULT '0' ,
  PRIMARY KEY (`id`),
  KEY `idx_guang_dlout_dlid` (`happy_id`),
  KEY `idx_guang_dlout_cat` (`created_at`),
  KEY `idx_guang_dlout_stdate` (`st_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优化建议：&lt;/p&gt;

&lt;p&gt;1、添加必要的索引&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; alter table guang_happy_outs add index `idx_of_t_s_id` (`t_s_id`, `id`);
Query OK, 0 rows affected (7 min 41.47 sec)
Records: 0  Duplicates: 0  Warnings: 0

explain select t_s_id from guang_happy_outs group by t_s_id\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: guang_happy_outs
         type: range
possible_keys: NULL
          key: idx_of_t_s_id
      key_len: 4
          ref: NULL
         rows: 201
        Extra: Using index for group-by
1 row in set (0.01 sec)

ERROR:
No query specified


查询时间：
    4818 rows in set (0.03 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不过针对大表而言，对于一些常用的查询，可以单独建立小表，在关联的小表上进行查询。&lt;/p&gt;
&lt;h4 id="十、EXPLAIN 返回type 为 ALL，全表扫描"&gt;十、EXPLAIN 返回 type 为 ALL，全表扫描&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
EXPLAIN SELECT `r_records`.*
FROM `r_records`
WHERE (create_time &amp;gt;= '2015-08-13'
       AND create_time &amp;lt; '2015-08-14'
       AND device_id !="0")\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: r_records
         type: ALL  &amp;lt;-- 看这里
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 10753575 &amp;lt;- 看这里
        Extra: Using where
1 row in set (0.01 sec)

ERROR:
No query specified


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;优化建议：&lt;/p&gt;

&lt;p&gt;1、添加关于  create_time 和 device_id 的联合索引。&lt;/p&gt;

&lt;p&gt;2、最好的方式就是单独单独建立统计表，针对每天的日志情况做统计。避免在大表上进行范围查询。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alter table r_records add index `idx_of_create_time` (`create_time`, `device_id`, `id`);
Query OK, 0 rows affected (4 min 14.59 sec)


EXPLAIN SELECT `r_records`.*
FROM `r_records`
WHERE (create_time &amp;gt;= '2015-08-13'
       AND create_time &amp;lt; '2015-08-14'
       AND device_id !="0")\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: r_records
         type: range
possible_keys: idx_of_create_time &amp;lt;-- 看这里
          key: idx_of_create_time
      key_len: 777  &amp;lt;-- 看这里
          ref: NULL
         rows: 1
        Extra: Using where
1 row in set (0.00 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;另一个例子&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT `happy_ni_nis`.*
FROM `happy_ni_nis`
ORDER BY n_total DESC LIMIT 10\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_ni_nis
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 66493186  &amp;lt;- 返回值太多，坏味道
        Extra: Using filesort &amp;lt;- 避免使用排序
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：13 sec&lt;/p&gt;

&lt;p&gt;优化建议：&lt;/p&gt;

&lt;p&gt;1、添加 关于 n_total 的索引&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; alter table happy_ni_nis add index `idx_of_n_total` (`n_total`, `id`);
Query OK, 0 rows affected (7 min 48.27 sec)
Records: 0  Duplicates: 0  Warnings: 0

EXPLAIN SELECT `happy_ni_nis`.*
FROM `happy_ni_nis`
ORDER BY n_total DESC LIMIT 10\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_ni_nis
         type: index
possible_keys: NULL
          key: idx_of_n_total
      key_len: 8
          ref: NULL
         rows: 10
        Extra:
1 row in set (0.01 sec)

ERROR:
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询时间：0.01 sec&lt;/p&gt;
&lt;h4 id="十一、针对大表的 count(id)"&gt;十一、针对大表的 count(id)&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from guang_happy_outs;
+-----------+
| count(id) |
+-----------+
|  69008543 |
+-----------+
1 row in set (31.14 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;千万表上的 count(id) 操作&lt;/p&gt;

&lt;p&gt;无解。&lt;/p&gt;

&lt;p&gt;如有同学知道怎么解决，请回复，3Q&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;在 &lt;a href="https://ruby-china.org/topics/26386" title=""&gt;select count (*) from table_name 为什么没有使用主键索引？&lt;/a&gt; 有详细的讨论。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select SQL_NO_CACHE count(id) from g_d_outs\G;
*************************** 1. row ***************************
count(id): 69008543
1 row in set (10.76 sec)

ERROR: 
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你想得到近似的统计值，使用 下面的这个方式 查找 &lt;code&gt;Rows&lt;/code&gt; 值，这种方式是非常快的。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; show table status where name = 'g_d_outs'\G;
*************************** 1. row ***************************
           Name: g_d_outs
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 69008796
 Avg_row_length: 71
    Data_length: 4965007360
Max_data_length: 0
   Index_length: 3560964096
      Data_free: 5242880
 Auto_increment: 138022949
    Create_time: 2015-08-14 18:46:13
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: ??????????
1 row in set (0.01 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;总结：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1、索引优化，最傻的办法，给查询语句添加覆盖索引。但不是最好的方式。&lt;/p&gt;

&lt;p&gt;2、将大表拆成小的汇总表。&lt;/p&gt;

&lt;p&gt;3、重在实践，MySQL 优化器在很多情况下不能给出，最快的实现方式。&lt;/p&gt;

&lt;p&gt;4、避免在大表上的 group by，order by，offset 操作，除非你知道如何优化的前提下。&lt;/p&gt;

&lt;p&gt;5、SQL WHERE 查询条件，尽量按照目前添加的索引顺序来。&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Thu, 20 Aug 2015 18:03:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/27004</link>
      <guid>https://ruby-china.org/topics/27004</guid>
    </item>
    <item>
      <title>Schema 与数据类型优化小技巧</title>
      <description>&lt;h4 id="一、手机号应该用什么类型的存储"&gt;一、手机号应该用什么类型的存储&lt;/h4&gt;
&lt;p&gt;int 的最大值为 21 亿，2**31，所以并不能保存手机号的百亿数据。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; create table big_int_test ( int_01 int(11), b_01 bigint(11), v_01 varchar(11));
Query OK, 0 rows affected (0.03 sec)

mysql&amp;gt; show create table big_int_test;
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table        | Create Table                                                                                                                                                            |
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| big_int_test | CREATE TABLE `big_int_test` (
  `int_01` int(11) DEFAULT NULL,
  `b_01` bigint(11) DEFAULT NULL,
  `v_01` varchar(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&amp;gt; insert into big_int_test (int_01, b_01, v_01) value (13522221111, 13522221111,13522221111);
ERROR 1264 (22003): Out of range value for column 'int_01' at row 1
mysql&amp;gt; insert into big_int_test (b_01, v_01) value (13522221111,13522221111);
Query OK, 1 row affected (0.00 sec)

mysql&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="二、尽量避免使用NULL"&gt;二、尽量避免使用 NULL&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;null 是一个未知的值  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;null 和任何值都不相等，包括它自己  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select null &amp;gt;0, null &amp;lt; 0 from dual;
+---------+----------+
| null &amp;gt;0 | null &amp;lt; 0 |
+---------+----------+
|    NULL |     NULL |
+---------+----------+
1 row in set (0.01 sec)

mysql&amp;gt; select null = null from dual;
+-------------+
| null = null |
+-------------+
|        NULL |
+-------------+
1 row in set (0.07 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;将某个值与 Null 进行比较的正确方法是使用 is 关键字，以及 is not 操作符&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
mysql&amp;gt; select * from areas where id in (3144, 3143, null, 3133);
+------+--------+--------------------------------+--------+
| id   | areaid | name                           | cityid |
+------+--------+--------------------------------+--------+
| 3133 | 654226 | 和布克赛尔蒙古自治县           | 654200 |
| 3143 | 659003 | 图木舒克市                     | 659000 |
| 3144 | 659004 | 五家渠市                       | 659000 |
+------+--------+--------------------------------+--------+
3 rows in set (0.02 sec)

select * from areas where id = 3144 or id = 3143 or id =3133 or id = null;

mysql&amp;gt; select * from areas where id not in (3144, 3143, null, 3133);
Empty set (0.00 sec)

转换成  select * from areas where id != 3144 and id != 3143 and id !=3133 and id != null;


&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Null 与排序&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;在排序时，null 值被认为是最大的（Oracle），在降序排序时会让你非常头大，因为 null 值排在了最前面。解决方法是使用 coalesce 进行&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQLServer 和 MySQL 认为 null 最小，Oracle 认为 null 最大&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;– 在输出时将 null 转换为 0 :

select name, coalesce(points, 0)

from users

order by 2 desc;

– 输出时保留 null, 但排序时转换为 0 :

select name, points

from users

order by coalesce(points, 0) desc;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://www.codeceo.com/article/sql-null.html" rel="nofollow" target="_blank" title=""&gt;sql-null&lt;/a&gt;&lt;br&gt;
&lt;a href="http://blog.csdn.net/smcwwh/article/details/6927613" rel="nofollow" target="_blank" title=""&gt;MYSQL、SQL Server、Oracle 数据库排序空值 null 问题及其解决办法&lt;/a&gt;&lt;br&gt;
&lt;a href="http://blog.itpub.net/519536/viewspace-626464/" rel="nofollow" target="_blank" title=""&gt;【NULLS】Oracle 对 SQL 排序后 NULL 值位置的“特殊关照” &lt;/a&gt;&lt;br&gt;
&lt;a href="http://blog.csdn.net/oxcow/article/details/6554168" rel="nofollow" target="_blank" title=""&gt;order by 语句对 null 字段的默认排序&lt;/a&gt;  &lt;/p&gt;
&lt;h4 id="三、DATETIME 和 TIMESTAMP 的区别"&gt;三、DATETIME 和 TIMESTAMP 的区别&lt;/h4&gt;
&lt;p&gt;DATETIME：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;占用 8 个字节&lt;/li&gt;
&lt;li&gt;这个类型能保存大范围的值，从 1001 年到 9999 年，精度为秒。&lt;/li&gt;
&lt;li&gt;封存到 'YYYYMMDDHHMMSS' 的整数中，与时区无关。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TIMESTAMP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;占用 4 个字节&lt;/li&gt;
&lt;li&gt;保存了 1970.1.1 午夜到现在的秒数，它和 UNIX 时间戳相同。&lt;/li&gt;
&lt;li&gt;只能表示从 1970 年到  2038 年。&lt;/li&gt;
&lt;li&gt;FROM_UNIXTIME()  UNIX_TIMESTAMP() 函数把时间戳和日期相互转换。&lt;/li&gt;
&lt;li&gt;存储时对当前的时区进行转换，检索时在转换回当前的时区。&lt;/li&gt;
&lt;li&gt;如果插入时没有指定第一个 TIMESTAMP 列的值，MySQL 则设置这个列的值为当前时间。在插入一行记录时，MySQL 默认也会更新第一个 TIMESTAMP 的列（除非在 UPDATE 语句中明确指定的值）。&lt;/li&gt;
&lt;li&gt;TIMESTAMP 列的默认值为 NOT NULL 这和其他数据类型不一样。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="四、数据库中价格应该怎么存的，为什么不用浮点数，如何证明浮点数不精确"&gt;四、数据库中价格应该怎么存的，为什么不用浮点数，如何证明浮点数不精确&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; CREATE TABLE test (c1 float(10,2),c2 decimal(10,2));
Query OK, 0 rows affected (0.29 sec)

mysql&amp;gt; insert into test values(131072.32,131072.32);
Query OK, 1 row affected (0.07 sec)

mysql&amp;gt; select * from test;
+-----------+-----------+
| c1        | c2        |
+-----------+-----------+
| 131072.31 | 131072.32 |
+-----------+-----------+
1 row in set (0.00 sec)

从上面的例子中我们看到c1列的值由131072.32变成了131072.31，这就是浮点数的不精确性造成的。

在MySQL中float、double（或real）是浮点数，decimal（或numberic）是定点数。
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt;&amp;gt; (10015.8*100.0).to_i
=&amp;gt; 1001579
&amp;gt;&amp;gt; 10015.8*100.0
=&amp;gt; 1001579.9999999999
&amp;gt;&amp;gt;  1001580.0.to_i
=&amp;gt; 1001580

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;今后关于浮点数和定点数的应用中，大家要记住以下几点：  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;浮点数存在误差问题。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;对货币等对精度敏感的数据，应该用定点数表示或存储；也可以用 BIGINT 代替 DECIMAL，将需要存储的货币单位根据最小的位数乘以相应的倍数即可。假设要存储财务数据精确到万分之一分，则可以把所有金额乘以一百万。 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;编程中，如果用到浮点数，要特别注意误差问题，并尽量避免做浮点数比较。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;要注意浮点数中一些特殊值的处理。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://c.biancheng.net/cpp/html/1466.html" rel="nofollow" target="_blank" title=""&gt;为 MySQL 选择合适的数据类型&lt;/a&gt;&lt;br&gt;
&lt;a href="http://wenku.baidu.com/view/11d8f46527d3240c8447efa8.html" rel="nofollow" target="_blank" title=""&gt;浮点数结构详解&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html" rel="nofollow" target="_blank" title=""&gt;浮点数的二进制表示&lt;/a&gt;&lt;br&gt;
&lt;a href="http://blog.163.com/yql_bl/blog/static/847851692008112013117685/" rel="nofollow" target="_blank" title=""&gt;浮点数的二进制表示学习笔记  &lt;/a&gt;  &lt;/p&gt;
&lt;h4 id="五、int 后面的数值和 varchar 后面的数值的区别"&gt;五、int 后面的数值和 varchar 后面的数值的区别&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MySQL 可以为整数类型指定宽度，例如 INT（11），对大多数应用来说是没有意义的。它不会限制值的合法范围，只是规定了 MySQL 的一些交互工具，用来显示字符的个数。对于存储和计算来说，INT(1) 和 INT(20) 是相同的&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;但是对于 varchar 类型来说，其后面显示的数值，表示其可以插入多少个字符串。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; create table int_test ( int_01 int(1), int_02 int(20));
Query OK, 0 rows affected (0.14 sec)

mysql&amp;gt; insert into int_test (int_01, int_02) value ( 123456, 123456);
Query OK, 1 row affected (0.04 sec)

mysql&amp;gt; select * from int_test;
+--------+--------+
| int_01 | int_02 |
+--------+--------+
| 123456 | 123456 |
+--------+--------+
1 row in set (0.02 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; create table varchar_test ( varchar_01 varchar(5), varchar_02 varchar(10));
Query OK, 0 rows affected (0.04 sec)

mysql&amp;gt; insert into varchar_test (varchar_01, varchar_02) value ("11111", "1111111");
Query OK, 1 row affected (0.01 sec)

mysql&amp;gt; insert into varchar_test (varchar_01, varchar_02) value ("111112", "1111111");
ERROR 1406 (22001): Data too long for column 'varchar_01' at row 1
mysql&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="六、varchar 和 char 的区别"&gt;六、varchar 和 char 的区别&lt;/h4&gt;
&lt;p&gt;VARCHAR：  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VARCHAR 类型用于存储可变长字符串，是最常见的字符串数据类型。
  它比定长类型更节省空间，因为它仅使用必要的空间&lt;/li&gt;
&lt;li&gt;VARCHAR 需要使用 1-2 个额外的字节记录字符串的长度。
  如果列的最大长度小于或等于 255 个字节，则只使用 1 个字节来表示长度，否则使用 2 个字节。
  所以 VARCHAR(1000) 的列则需要 1002 个字节。&lt;/li&gt;
&lt;li&gt;在 5.0 或更好版本，MySQL 在存储和检索时会保留末尾空格。&lt;/li&gt;
&lt;li&gt;InnoDB 则更灵活，它可以把过长的 VARCHAR 存储为 BLOB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CHAR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CHAR 类型是定长的，MySQL 总是根据定义的字符串长度分配足够的空间。&lt;/li&gt;
&lt;li&gt;CHAR 适合存储很短的字符串，或者所有值都很接近的一个长度。例如
  CHAR 就非常合适存储密码的 MD5 值，因为这个是定长的。&lt;/li&gt;
&lt;li&gt;对于经常变更的数据，CHAR 也比 VARCHAR
  更好，因为定长的 CHAR 类型不容易产生碎片&lt;/li&gt;
&lt;li&gt;对于非常短的列，CHAR 比 VARCHAR 在存储空间上也更有效率。例如用
  CHAR(1)
  来存储只有 Y 和 N 的只，如果采用单字节字符集只需要一个字节，但是
  VARCHAR(1) 却需要两个字节，因为还有一个用来记录长度。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE char_test(
    char_col1 CHAR(1),
    char_col2 CHAR(10),
    varchar_col1 CHAR(1),
    varchar_col2 CHAR(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO char_test VALUES ('Y', 'string1', "Y", "string1"), ('Y', ' string1', "Y", " string1"), ('Y', 'string1 ', "Y", "string1 ");


SELECT LENGTH(char_col1), LENGTH(varchar_col1), CONCAT("'", char_col2, "'") FROM char_test;
SELECT LENGTH(char_col1), LENGTH(varchar_col1), CONCAT("'", varchar_col2, "'") FROM char_test;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="七、varchar 最大的存储空间"&gt;七、varchar 最大的存储空间&lt;/h4&gt;
&lt;p&gt;字符是指计算机中使用的字母、数字、汉字和符号。 &lt;/p&gt;

&lt;p&gt;字节是计算机信息技术中存储容量的一种计量单位，也表示一些计算机编程语言中的数据类型和语言字符。&lt;/p&gt;

&lt;p&gt;UTF-8 一个汉字=3 个字节，英文是一个字节
GBK   一个汉字=2 个字节，英文是一个字节&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;由于 MySQL 的记录行长度是有限制的，不是无限长的，这个长度是 64K，即 65535 个字节，对所有的表都是一样的。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在 UTF-8 状态下，汉字最多可以存 21844 个字符串，英文也为 21844 个字符串。&lt;br&gt;
在 GBK 状态下，汉字最多可以存 32766 个字符串，英文也为 32766 个字符串。  &lt;/p&gt;

&lt;p&gt;varchar(n) 其中 n 表示字符，无论汉字和英文，MySQL 都能存入 n 个字符，但实际存入其中的字节长度有所区别。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MySQL 对于变长类型的字段会有 1-2 个字节来保存字符长度。&lt;/li&gt;
&lt;li&gt;当字符数小于等于 255 时，MySQL 只用 1 个字节来记录，因为 2 的 8 次方减 1 只能存到 255。
当字符数多余 255 时，就得用 2 个字节来存长度了。&lt;/li&gt;
&lt;li&gt;在 UTF-8 状态下的 varchar，最大只能到 (65535 - 2) / 3 = 21844 余 1。&lt;/li&gt;
&lt;li&gt;在 GBK 状态下的 varchar, 最大只能到 (65535 - 2) / 2 = 32766 余 1。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/topics/24920" title=""&gt;MySQL 数据库 varchar 到底可以存多少个汉字，多少个英文呢？我们来搞搞清楚&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="八、数据库碎片是什么东西，有什么影响"&gt;八、数据库碎片是什么东西，有什么影响&lt;/h4&gt;
&lt;p&gt;MySQL 具有相当多不同种类的存储引擎来实现列表中的数据存储功能。&lt;strong&gt;每当 MySQL 从你的
列表中删除了一行内容，该段空间就会被留空。而在一段时间内的大量删除操作，
会使这种留空的空间变得比存储列表内容所使用的空间更大。&lt;/strong&gt;
当 MySQL 对数据进行扫描时，它扫描的对象实际是列表的容量需要求的上限
也就是数据被写入的区域中处于峰值位置的部分。如果进行新的插入操作，
MySQL 将尝试利用这些留空的区域，但仍然无法将其彻底占用。&lt;/p&gt;

&lt;p&gt;这就是为什么不建议删除数据库的数据。但是你可以使用
一个状态来描述，描述该状态是否可用&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;data_free 表示我们删除后所产生的留空空间。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://database.51cto.com/art/201103/251967.htm" rel="nofollow" target="_blank" title=""&gt;浅析 MySQL 数据碎片的产生&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;查看线上数据库中 Table
Infomation 时发现有一个日志表数据大小和索引大小有 915M，但实际上行数只有 92 行。
该表需要频繁插入并且会定时去删掉旧的记录。该表上建立了索引，所以应该是产生了大量的碎片
使用 Optimize table
表明，优化后大小变为 2.19M，少了很多，同时可以看出该表上的索引建的多余，因为插入操作比查询操作要多
很多，而且查询不多，查询的数量也变小。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pengbotao.cn/mysql-suipian-youhua.html" rel="nofollow" target="_blank" title=""&gt;mysql-suipian-youhua&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="九、什么情况下会使用binary 查询"&gt;九、什么情况下会使用 binary 查询&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;BINARY 不是函数，是类型转换运算符，它用来强制它后面的字符串为一个二进制字符串，可以理解为在字符串比较的时候区分大小写&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;因为有的 MySQL 特别是 4.x 以前以前的对于字符串检索不准确，所以在检索的时候加上
binary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL 中 字符串和字符串的比较是不靠谱的，在二进制层次上比较靠谱&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It an efficient have of comparing byte to byte instead of character to character&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create table user_test(
  id int(9) unsigned NOT NULL auto_increment,
  username varchar(30) NOT NULL default '',
  primary key (id)
);


INSERT INTO user_test (username) VALUES('美文');
INSERT INTO user_test (username) VALUES('美国项目');
INSERT INTO user_test (username) VALUES('李文');
INSERT INTO user_test (username) VALUES('老唐');
INSERT INTO user_test (username) VALUES('梦漂');
INSERT INTO user_test (username) VALUES('龙武');
INSERT INTO user_test (username) VALUES('夏');


mysql&amp;gt; select * from user_test;
+----+--------------+
| id | username     |
+----+--------------+
|  1 | 美文         |
|  2 | 美国项目     |
|  3 | 李文         |
|  4 | 老唐         |
|  5 | 梦漂         |
|  6 | 龙武         |
|  7 | 夏           |
+----+--------------+
7 rows in set (0.00 sec)


mysql&amp;gt; select * from user_test where username =  '夏';
+----+----------+
| id | username |
+----+----------+
|  7 | 夏       |
+----+----------+
1 row in set (0.00 sec)

mysql&amp;gt; select * from user_test where username =  '夏 ';
+----+----------+
| id | username |
+----+----------+
|  7 | 夏       |
+----+----------+
1 row in set (0.00 sec)

mysql&amp;gt; select * from user_test where username = BINARY '夏';
+----+----------+
| id | username |
+----+----------+
|  7 | 夏       |
+----+----------+
1 row in set (0.00 sec)

mysql&amp;gt; select * from user_test where username = BINARY '夏 ';
Empty set (0.00 sec)


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;如果有长字符串的比较，的另一种方案。可以适当添加一个字段，来存储该字符串的 crc32 值。
先比较 crc32 值，然后再比较字符串值。提高比较的速度和准确性。&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crc = crc32("Hello")
=&amp;gt; 4157704578
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://www.jb51.net/article/41546.htm" rel="nofollow" target="_blank" title=""&gt;MySQL 的 binary 解决 MySQL 数据大小写敏感问题的方法&lt;/a&gt;&lt;br&gt;
&lt;a href="http://stackoverflow.com/questions/11133257/why-the-binary-in-a-select-statement" rel="nofollow" target="_blank" title=""&gt;Why the 'BINARY' in a SELECT statement?&lt;/a&gt; 
&lt;a href="http://dev.MySQL.com/doc/refman/5.0/en/charset-binary-op.html" rel="nofollow" target="_blank" title=""&gt;charset-binary-op&lt;/a&gt; &lt;/p&gt;
&lt;h4 id="十、VARCHAR（5） 和 VARCHAR（200）存储上的区别，排序上的区别"&gt;十、VARCHAR（5）和 VARCHAR（200）存储上的区别，排序上的区别&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;相比较而言，varchar(5) 所占用的空间相对比较小。&lt;/li&gt;
&lt;li&gt;在排序时，varchar(5) 所占用的空间相对比 varchar(200) 要少。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="十一、1000w的数据，如果在ORDER BY 中使用到varchar(1000)这个列，并且查询扫描整个表，为了排序就需要超过30GB的临时表"&gt;十一、1000w 的数据，如果在 ORDER BY 中使用到 varchar(1000) 这个列，并且查询扫描整个表，为了排序就需要超过 30GB 的临时表&lt;/h4&gt;
&lt;p&gt;最坏情况下的长度分配对于排序也是一样的。
意思就是在排序的时候使用的是分配长度的最大长度。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 GB = 1000 MB = 1 000 000 KB = 1 000 000 000 B
1 MB = 1 000KB = 1 000 000 B

3000 * 10 000 000 = 30 000 000 000 B = 30GB
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="十二、排序 使用 FIND_IN_SET 进行按顺序排序"&gt;十二、排序 使用 FIND_IN_SET 进行按顺序排序&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt;  explain
    -&amp;gt;  select id, title
    -&amp;gt;  from happy_for_ni_deals t
    -&amp;gt;  where t.id in (1014694, 1014693, 1014697, 1014691)
    -&amp;gt;  order by FIND_IN_SET(t.id, '1014694,1014693,1014697,1014691');
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    4 | Using where; Using filesort |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------------+
1 row in set (0.01 sec)

4、
mysql&amp;gt;  explain
    -&amp;gt;  select id, title
    -&amp;gt;  from happy_for_ni_deals t
    -&amp;gt;  where t.id in (1014694, 1014693, 1014697, 1014691);
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    4 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.01 sec)

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="十三、通用的设计实践，在“查找表”时采用整数主键而避免采用基于字符串的值进行关联"&gt;十三、通用的设计实践，在“查找表”时采用整数主键而避免采用基于字符串的值进行关联&lt;/h4&gt;
&lt;p&gt;由于根据字符串的关联，在查找排序的时候，需要占用更多的空间，消耗更多的资源。
  &lt;a href="http://blog.codinglabs.org/articles/theory-of-mysql-index.html" rel="nofollow" target="_blank" title=""&gt;theory-of-mysql-index&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="十四、选择标识符"&gt;十四、选择标识符&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;标识列选择数据类型时，应该选择跟关联表中的对应列一样的类型。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;混用不同数据类型可能导致性能问题，及时没有性能影响，在比较操作时饮食类型转换也可以能导致很难发现的错误。
对于完全“随机”的字符串也需要多加注意，&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;例如 MD5（），SHA1（）或 UUID() 产生的字符串，&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这些函数生成的新值会任意分布在很大的空间内，这会导致 INSERT 以及一些 SELECT 语句变得很慢
  使用 UUID() 并非一无是处，在分布式数据库中，使用 UUID() 是一个不错的选择。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/topics/24509" title=""&gt;MySQL 用 UUID 作为主键，实际使用中有什么问题&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;下面例子中关联查询的时候，使用一个字符串和 int 型主键 ID 进行串联。会导致索引使用不上。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; EXPLAIN SELECT *
    -&amp;gt; FROM happy_for_ni_tb_shops AS t
    -&amp;gt; INNER JOIN candidate_happy_for_ni_deals AS c_d
    -&amp;gt; WHERE t.id = c_d.cid \G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c_d
         type: ALL
possible_keys: idx_cid
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra: Range checked for each record (index map: 0x2)
2 rows in set (0.07 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://ruby-china.org/topics/26352" title=""&gt;MySQL 为什么需要一个主键&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="十五、特殊类型数据"&gt;十五、特殊类型数据&lt;/h4&gt;
&lt;p&gt;MySQL 提供 INET_ATON() 和 INET_NEOA() 函数在 IP 地址上进行转换&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; SELECT INET_ATON('209.207.224.40'), INET_NTOA(3520061480) FROM dual;
+-----------------------------+-----------------------+
| INET_ATON('209.207.224.40') | INET_NTOA(3520061480) |
+-----------------------------+-----------------------+
|                  3520061480 | 209.207.224.40        |
+-----------------------------+-----------------------+
1 row in set (0.02 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="十六、JOIN 驱动表"&gt;十六、JOIN 驱动表&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;inner join 驱动顺序由优化器自己制定，如果优化器选择有误可以使用 straight_join 自己指定驱动顺序以达到优化的目的。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;left join 驱动顺序是固定的，left join 左边的表为驱动表，右边为匹配表，right join 则刚好相反。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;存在 group by 或者 order by 子句的关联查询中，如果引用的字段是驱动表的字段那么分组或者排序是可以使用到索引的。但是如果引用的是其他匹配表的字段，那么分组或者排序动作则无法使用索引。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;内连接就是检索出与连接条件完全匹配的数据行；而外连接则保留了所有驱动表的数据，匹配表中无法匹配的数据则以 null 输出。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;驱动表的结果集，越小越好。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://hidba.ga/2014/09/26/join-query-in-mysql/" rel="nofollow" target="_blank" title=""&gt;join-query-in-mysql&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="十七、从父表冗余一些数据到子表的理由是排序的需要，虽然不符合范式要求。"&gt;十七、从父表冗余一些数据到子表的理由是排序的需要，虽然不符合范式要求。&lt;/h4&gt;
&lt;p&gt;happy_for_ni_deals 表和 happy_for_ni_tb_shops 表的关联查询，但是最后使用了 happy_for_ni_tb_shops.grade 做 desc&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT  `happy_for_ni_deals`.*
FROM `happy_for_ni_deals`
  INNER JOIN `happy_for_ni_tb_shops`
  ON `happy_for_ni_tb_shops`.`id` = `happy_for_ni_deals`.`happy_for_ni_tb_shop_id`
    LEFT JOIN candidate_happy_for_ni_deals
    on happy_for_ni_deals.candidate_happy_for_ni_deal_id = candidate_happy_for_ni_deals.id
      LEFT JOIN happy_for_ni_deal_infos
      on happy_for_ni_deal_infos.happy_for_ni_deal_id = happy_for_ni_deals.id
WHERE ( happy_for_ni_deals.bg_tag_id &amp;gt; 0 )
  AND (happy_for_ni_deals.complete_status = 1)
ORDER BY happy_for_ni_tb_shops.grade DESC, happy_for_ni_deals.id DESC LIMIT 20 OFFSET 0

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_deals
         type: range
possible_keys: index_happy_for_ni_deals_on_happy_for_ni_tb_shop_id_and_id,idx_bg_tag_pub_beg,idx_bg_tag_pub_end
          key: idx_bg_tag_pub_beg
      key_len: 4
          ref: NULL
         rows: 1
        Extra: Using index condition; Using where; Using temporary; Using filesort  &amp;lt;- 坏味道，temporary &amp;amp;&amp;amp; filesort

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将&lt;code&gt;happy_for_ni_tb_shops&lt;/code&gt;表上的 &lt;code&gt;grade&lt;/code&gt; 赋值到 &lt;code&gt;happy_for_ni_deals&lt;/code&gt; 上，在代码中将&lt;code&gt;happy_for_ni_tb_shops&lt;/code&gt; 表 &lt;code&gt;grade&lt;/code&gt; 逻辑也同步到&lt;code&gt;happy_for_ni_deals&lt;/code&gt;上
然后加索引。这样排序，会快一些。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE happy_for_ni_deals ADD COLUMN grade int(11) not null;
ALTER TABLE happy_for_ni_deals ADD INDEX `idx_of_grade` (grade, id);
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT  `happy_for_ni_deals`.*
FROM `happy_for_ni_deals`
  INNER JOIN `happy_for_ni_tb_shops`
  ON `happy_for_ni_tb_shops`.`id` = `happy_for_ni_deals`.`happy_for_ni_tb_shop_id`
    LEFT JOIN candidate_happy_for_ni_deals
    on happy_for_ni_deals.candidate_happy_for_ni_deal_id = candidate_happy_for_ni_deals.id
      LEFT JOIN happy_for_ni_deal_infos
      on happy_for_ni_deal_infos.happy_for_ni_deal_id = happy_for_ni_deals.id
WHERE ( happy_for_ni_deals.bg_tag_id &amp;gt; 0 )
  AND (happy_for_ni_deals.complete_status = 1)
ORDER BY happy_for_ni_deals.grade DESC, happy_for_ni_deals.id DESC LIMIT 20 OFFSET 0

*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_deals
         type: ref
possible_keys: index_happy_for_ni_deals_on_happy_for_ni_tb_shop_id_and_id,idx_bg_tag_pub_beg,idx_bg_tag_pub_end
          key: index_happy_for_ni_deals_on_happy_for_ni_tb_shop_id_and_id
      key_len: 4
          ref: tao800_test9.happy_for_ni_tb_shops.id
         rows: 1
        Extra: Using where
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="十八、MySQL 视图"&gt;十八、MySQL 视图&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;什么是视图？视图是由查询结果形成的一张虚拟表。&lt;/li&gt;
&lt;li&gt;什么时候要用到视图？如果某个查询结果出现的非常频繁，也就是说，要经常拿到这个查询结果来做子查询。&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;视图的创建语法：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create view 视图名 as select 语句；
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;使用视图有什么好处？
**  1、简化查询语句。将经常用到的子查询做成视图。**
**  2、可以进行权限控制。视图里只开放部分数据列。**
**  3、大数据分表时可以用到。**&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://www.cnblogs.com/wangtao_20/archive/2011/02/24/1964276.html" rel="nofollow" target="_blank" title=""&gt;MySQL 视图学习总结&lt;/a&gt;
&lt;a href="http://www.cnblogs.com/zzwlovegfj/archive/2012/06/23/2559596.html" rel="nofollow" target="_blank" title=""&gt;MySQL 之视图&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="十九、更快地读，更慢的写。高性能数据库的设计"&gt;十九、更快地读，更慢的写。高性能数据库的设计&lt;/h4&gt;
&lt;p&gt;为了提升查询的速度，经常会需要见一些额外的索引，增加冗余列，甚至是创建缓存表和汇总表。这些方法会增加写查询的负担，也需要额外的维护任务，但是在设计高性能数据库时，这些都是最常见的技巧。虽然写操作变得更慢了，但更显著地提高了读操作的性能&lt;/p&gt;
&lt;h4 id="二十、加快ALTER TBALE 操作的速度"&gt;二十、加快 ALTER TBALE 操作的速度&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;ALTER TABLE 操作需要花费数小时时间甚至数天才能完成。&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;大部分 ALTER TABLE 操作将导致 MySQL 服务中断。&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;不是所有的 ALTER TABLE 操作都会引起表重建。&lt;/strong&gt;  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE sakila.film MODIFY COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;

所有的MODIFY COLUMN 操作都将导致表重建。所以这种操作是很慢的。

&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE sakila.film ALTER COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;

这个语句会直接修改.frm 文件而不设计表数据。所以，这个操作是非常快的。

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ALTER TABLE 允许使用 ALTER COLUMN、MODIFY COLUMN 和 CHANGE COLUMN 语句修改列，这三种操作都是不一样的。&lt;/p&gt;
&lt;h4 id="二十一、给大表添加索引或字段该如何操作"&gt;二十一、给大表添加索引或字段该如何操作&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;在构建索引的工作被延迟到数据完全载入以后，这个时候已经可以通过排序来构建索引了。这样做会快很多，并且使得索引树的碎片更少、更紧凑。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1、clone 新表  &lt;/p&gt;

&lt;p&gt;2、先删除所有的非唯一性索引，然后增加新的列，最后重新创建删除掉的索引。  &lt;/p&gt;

&lt;p&gt;3、交换新表和旧表  &lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 11 Aug 2015 15:19:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/26873</link>
      <guid>https://ruby-china.org/topics/26873</guid>
    </item>
    <item>
      <title>MySQL 慢查询优化实战一例</title>
      <description>&lt;h3 id="慢查询优化"&gt;慢查询优化&lt;/h3&gt;&lt;h4 id="一、查看表结构"&gt;一、查看表结构&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `happy_for_ni_labels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name_chn` varchar(255) NOT NULL DEFAULT '0' COMMENT '标签的名字',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '标签状态',
  `xx_tag_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联XxTag#ID',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `xxxxx_tag_id` int(11) NOT NULL DEFAULT '0' COMMENT 'xxxxx_tags.id(新分类体系)',
  PRIMARY KEY (`id`),
  KEY `idx_name_chn_with_id` (`name_chn`,`id`),
  KEY `idx_xx_tag_id_with_id` (`xx_tag_id`,`id`),
  KEY `idx_ptag_id` (`xxxxx_tag_id`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=719 DEFAULT CHARSET=utf8 COMMENT='报名活动标签'

CREATE TABLE `happy_for_ni_label_links` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `happy_for_ni_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联HappyForNi#ID',
  `checked_happy_for_ni_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联CheckedHappyForNi#ID',
  `label_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联HappyForNiLabel#ID',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '关联状态(可用、删除)',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_label_id_with_id` (`label_id`,`id`),
  KEY `idx_status_happy_for_ni_id_with_id` (`happy_for_ni_id`,`status`,`id`),
  KEY `idx_status_checked_happy_for_ni_id_with_id` (`checked_happy_for_ni_id`,`status`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2048836 DEFAULT CHARSET=utf8 COMMENT='报名活动标签关联表'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行查询计划可知&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;explain SELECT `happy_for_ni_labels`.`id`
 FROM `happy_for_ni_labels`
 INNER JOIN `happy_for_ni_label_links`
  ON `happy_for_ni_labels`.`id` = `happy_for_ni_label_links`.`label_id` WHERE `happy_for_ni_label_links`.`happy_for_ni_id` = 3369231

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_labels
         type: index
possible_keys: PRIMARY
          key: idx_xx_tag_id_with_id
      key_len: 8
          ref: NULL
         rows: 461
        Extra: Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_label_links
         type: ref
possible_keys: idx_label_id_with_id
          key: idx_label_id_with_id
      key_len: 4
          ref: my_local_test.happy_for_ni_labels.id
         rows: 1872
        Extra: Using WHERE
2 rows in set (0.00 sec)

ERROR:
No query specified



&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本来想用到 &lt;code&gt;idx_status_happy_for_ni_id_with_id&lt;/code&gt;  但是实际上只用到了 &lt;code&gt;idx_label_id_with_id&lt;/code&gt; 这个索引，所以根据现有的资料。&lt;/p&gt;

&lt;p&gt;优化有两种方案&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;去掉现有的索引，重新生成索引。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;重用现在的索引，修改查询语句。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="二、去掉现有的索引，重新生成索引。"&gt;二、去掉现有的索引，重新生成索引。&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; SELECT count(id), status
    -&amp;gt; FROM happy_for_ni_label_links
    -&amp;gt; GROUP BY status;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    112463
Current database: my_local_test

+-----------+--------+
| count(id) | status |
+-----------+--------+
|    980377 |      0 |
+-----------+--------+
1 row in set (2.27 sec)


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;status&lt;/code&gt; 只有为 &lt;code&gt;0&lt;/code&gt; 的值。这里其实是个败笔。创建这个表的作者（也就是我），当时考虑到由于业务需要，会查询各种不同状态下的数据量，故设计了这个&lt;code&gt;status&lt;/code&gt;。但实际情况，该状态，只有一个为 0 的值，不需要看索引记录也知道，该列上的选择性太差。建议，不要将该列放在索引第一位。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;删除索引
ALTER TABLE `happy_for_ni_label_links` DROP INDEX `idx_status_happy_for_ni_id_with_id`;

ALTER TABLE `happy_for_ni_label_links` DROP INDEX `idx_status_checked_happy_for_ni_id_with_id`;


添加索引
ALTER TABLE `happy_for_ni_label_links`  ADD INDEX `idx_status_happy_for_ni_id_with_id` (happy_for_ni_id, status, id);
Query OK, 0 rows affected (3.52 sec)

ALTER TABLE `happy_for_ni_label_links`  ADD INDEX `idx_status_checked_happy_for_ni_id_with_id` ( checked_happy_for_ni_id, status, id);
Query OK, 0 rows affected (3.57 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最终结果如下（不需要修改查询语句，重建索引即可）&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; explain SELECT `happy_for_ni_labels`.`id`
    -&amp;gt;  FROM `happy_for_ni_labels`
    -&amp;gt;  INNER JOIN `happy_for_ni_label_links`
    -&amp;gt;   ON `happy_for_ni_labels`.`id` = `happy_for_ni_label_links`.`label_id` WHERE `happy_for_ni_label_links`.`happy_for_ni_id` = 3369231\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_label_links
         type: ref
possible_keys: idx_label_id_with_id,idx_status_happy_for_ni_id_with_id
          key: idx_status_happy_for_ni_id_with_id
      key_len: 4
          ref: const
         rows: 1
        Extra:
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_labels
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: my_local_test.happy_for_ni_label_links.label_id
         rows: 1
        Extra: Using index
2 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对应的 &lt;code&gt;key&lt;/code&gt;, &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;rows&lt;/code&gt; 都有明显的优化。&lt;strong&gt;所以优化已经生效。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;但是注意&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;完成这些数据数据定义索引修改的（DDL），总共花费了 3.52 + 3.57 = 7.09 秒。在此期间，由于 ALTER 语句是阻塞操作，因此所有为表添加和修改数据的额外请求都被阻塞了。此时 SELECT 语句也会被阻塞而无法完成。并且修改大表的索引，会产生碎片和一些临时空间。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;建议指数：三颗星&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="三、重用现在的索引，修改查询语句"&gt;三、重用现在的索引，修改查询语句&lt;/h4&gt;
&lt;p&gt;首先分析下该表上索引基数（Cardinality），重点查看下 &lt;code&gt;idx_status_happy_for_ni_id_with_id&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; *************************** 2. row ***************************
        Table: happy_for_ni_label_links
   Non_unique: 1
     Key_name: idx_status_happy_for_ni_id_with_id
 Seq_in_index: 1
  Column_name: status
    Collation: A
  Cardinality: 18
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 3. row ***************************
        Table: happy_for_ni_label_links
   Non_unique: 1
     Key_name: idx_status_happy_for_ni_id_with_id
 Seq_in_index: 2
  Column_name: happy_for_ni_id
    Collation: A
  Cardinality: 996079
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 4. row ***************************
        Table: happy_for_ni_label_links
   Non_unique: 1
     Key_name: idx_status_happy_for_ni_id_with_id
 Seq_in_index: 3
  Column_name: id
    Collation: A
  Cardinality: 996079
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;根据上述分析得出，&lt;code&gt;status&lt;/code&gt; 的索引基数为 18， &lt;code&gt;happy_for_ni_id&lt;/code&gt; 的索引基数为 996079， &lt;code&gt;id&lt;/code&gt; 的索引基数为 &lt;code&gt;996079&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;一般来说，将索引基数大的放置在索引的最前面。
那为什么要把索引基数大的放置在索引最前面呢？因为所以基数大，代表在数据库中唯一性值最高，唯一性值更高，代表的查询效率更快。如果数据库中，该列索引基数不高，查询要么关联其他字段，要么重复回表操作，CPU，内存和网络消耗更高一些。&lt;/p&gt;

&lt;p&gt;但是这里为什么要把&lt;code&gt;status&lt;/code&gt; 索引基数低的值放置在索引的最前面呢？
考虑到业务需要，会查询各种状态下的数据量，所以将 &lt;code&gt;status&lt;/code&gt; 放在索引的最前面。该字段也是为了将来业务系统做扩展使用。&lt;/p&gt;

&lt;p&gt;根据&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
KEY `idx_status_happy_for_ni_id_with_id` (`status`,`happy_for_ni_id`,`id`)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只有下面三种情况会使用到索引&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1、WHERE happy_for_ni_label_links.status = xxx

2、WHERE happy_for_ni_label_links.status = xxx AND  happy_for_ni_label_links.happy_for_ni_id = xxx

3、WHERE happy_for_ni_label_links.status = xxx AND  happy_for_ni_label_links.happy_for_ni_id = xxx AND  happy_for_ni_label_links.id = xxx 

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么，我们的 SQL 就可以改写成&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
mysql&amp;gt; explain select `happy_for_ni_labels`.`id` from `happy_for_ni_labels` inner join `happy_for_ni_label_links` on `happy_for_ni_labels`.`id` = `happy_for_ni_label_links`.`label_id` WHERE `happy_for_ni_label_links`.status = 0 AND `happy_for_ni_label_links`.`happy_for_ni_id` = 3369231\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_label_links
         type: ref
possible_keys: idx_status_happy_for_ni_id_with_id,idx_status_checked_happy_for_ni_id_with_id,idx_label_id_with_id
          key: idx_status_happy_for_ni_id_with_id
      key_len: 5
          ref: const,const
         rows: 1
        Extra:
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: happy_for_ni_labels
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: my_local_test.happy_for_ni_label_links.label_id
         rows: 1
        Extra: Using index
2 rows in set (0.00 sec)

ERROR:
No query specified

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;key&lt;/code&gt; 由  &lt;code&gt;idx_xx_tag_id_with_id&lt;/code&gt; 变为  &lt;code&gt;idx_status_happy_for_ni_id_with_id&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ref&lt;/code&gt;都由&lt;code&gt;NULL&lt;/code&gt;类型，变为常量索引类型&lt;code&gt;const&lt;/code&gt;, 看来效率提升的确实不少。&lt;/p&gt;

&lt;p&gt;扫描的记录数，也有 &lt;code&gt;461&lt;/code&gt;,&lt;code&gt;1872&lt;/code&gt; 变为了现在的  &lt;code&gt;1&lt;/code&gt;,&lt;code&gt;1&lt;/code&gt;  说明优化确实起到了作用。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;建议指数：五颗星&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jianshu.com/p/4fb6386f415e" rel="nofollow" target="_blank" title=""&gt;我的简书&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Mon, 27 Jul 2015 23:12:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/26668</link>
      <guid>https://ruby-china.org/topics/26668</guid>
    </item>
    <item>
      <title>关于 MySQL 前置索引</title>
      <description>&lt;h4 id="一、前置索引的好处"&gt;一、前置索引的好处&lt;/h4&gt;
&lt;p&gt;使用前置索引的好处&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Normally, the entire value of a column is used to build the index - this is fine for short data types (integers and the like) but can result in a lot of data in the index for longer data types (CHAR and VARCHAR, for example). Using an index prefix allows you to make a trade off between the space required for the index and the cardinality of the index.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="二、前置索引的坑"&gt;二、前置索引的坑&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;第一种情况&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;索引的长度和对应字段中的长度一致（name 与 idx_of_name）&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| areas | CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `areaid` varchar(20) NOT NULL,
  `name` varchar(50) NOT NULL,
  `cityid` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_of_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3145 DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&amp;gt; explain select id, name from areas order by name;
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
|  1 | SIMPLE      | areas | index | NULL          | idx_of_name | 152     | NULL | 3144 | Using index |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql&amp;gt; explain select * from areas where name = '龙潭区';
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                 |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | areas | ref  | idx_of_name   | idx_of_name | 152     | const |    1 | Using index condition |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)

mysql&amp;gt;  explain select id, name from areas group by name;
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
|  1 | SIMPLE      | areas | index | idx_of_name   | idx_of_name | 152     | NULL | 3144 | Using index |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
1 row in set (0.01 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;第二种情况：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;索引的长度和对应字段中的长度不一致（name 与 idx_of_name）&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| areas | CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `areaid` varchar(20) NOT NULL,
  `name` varchar(50) NOT NULL,
  `cityid` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_of_name` (`name`(6))
) ENGINE=InnoDB AUTO_INCREMENT=3145 DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&amp;gt; explain select id, name from areas order by name;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | areas | ALL  | NULL          | NULL | NULL    | NULL | 3144 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.01 sec)

mysql&amp;gt; explain select * from areas where name = '龙潭区';
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
|  1 | SIMPLE      | areas | ref  | idx_of_name   | idx_of_name | 20      | const |    1 | Using where |
+----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+
1 row in set (0.01 sec)

mysql&amp;gt; explain select id, name from areas group by name;
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                           |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
|  1 | SIMPLE      | areas | ALL  | NULL          | NULL | NULL    | NULL | 3144 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;虽然在查询上用到了索引，但是在排序时，索引不生效。&lt;/p&gt;

&lt;p&gt;使用索引就一定能加快查询效率么？不一定。上面的例子就告诉我们，前置索引
并不是一个万能药，它的确可以帮助我们在一个过长的字段中建立索引。&lt;code&gt;但同时也会导致排序（order by, group by）查询都无法使用前置索引。&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="三、如何计算出前置索引的最佳长度"&gt;三、如何计算出前置索引的最佳长度&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;关于如何计算出，最恰当的设置索引的长度，总体思想：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 全列选择性
SELECT COUNT(DISTINCT column_name) / COUNT(*) FROM table_name;

# 测试某一长度前缀的选择性
SELECT COUNT(DISTINCT LEFT(column_name, prefix_length)) / COUNT(*) FROM table_name;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;当前置的选择性越接近全列的选择性的时候，索引效果越好。&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;通常可以索引开始的几个字符，而不是全部值，以节约空间并取得好的性能。这使索引需要的空间变小，但是也会降低选择性。索引选择性不重复的索引值和表中所有行的比值。高选择性的索引有好处，因为它使MySQL在查找匹配的时候可以过滤更多的行。唯一索引的选择率为1，为最佳值&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;具体操作如下：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `areaid` varchar(20) NOT NULL,
  `name` varchar(50) NOT NULL,
  `cityid` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3145 DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&amp;gt; select count(distinct(name))/count(id) from areas;
+---------------------------------+
| count(distinct(name))/count(id) |
+---------------------------------+
|                          0.8954 |
+---------------------------------+
1 row in set (0.01 sec)

mysql&amp;gt; select count(distinct left(name, 2))/count(id) from areas;
+-----------------------------------------+
| count(distinct left(name, 2))/count(id) |
+-----------------------------------------+
|                                  0.8648 |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql&amp;gt; select count(distinct left(name, 3))/count(id) from areas;
+-----------------------------------------+
| count(distinct left(name, 3))/count(id) |
+-----------------------------------------+
|                                  0.8909 |
+-----------------------------------------+
1 row in set (0.01 sec)

mysql&amp;gt; select count(distinct left(name, 5))/count(id) from areas;
+-----------------------------------------+
| count(distinct left(name, 5))/count(id) |
+-----------------------------------------+
|                                  0.8941 |
+-----------------------------------------+
1 row in set (0.01 sec)

mysql&amp;gt; select count(distinct left(name, 6))/count(id) from areas;
+-----------------------------------------+
| count(distinct left(name, 6))/count(id) |
+-----------------------------------------+
|                                  0.8954 |
+-----------------------------------------+
1 row in set (0.00 sec)

前置索引为6时，选择性和列值选择性相同。那么就设定该索引的长度为6位。

mysql&amp;gt; select max(length(name)) from areas;
+-------------------+
| max(length(name)) |
+-------------------+
|                45 |
+-------------------+
1 row in set (0.11 sec)

mysql&amp;gt; select * from areas where length(name) = 45;
+------+--------+-----------------------------------------------+--------+
| id   | areaid | name                                          | cityid |
+------+--------+-----------------------------------------------+--------+
| 2624 | 530925 | 双江拉祜族佤族布朗族傣族自治县                | 530900 |
| 2965 | 622927 | 积石山保安族东乡族撒拉族自治县                | 622900 |
+------+--------+-----------------------------------------------+--------+
2 rows in set (0.01 sec)


&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="四、索引的最大长度"&gt;四、索引的最大长度&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select 255 * 3 from dual;
+---------+
| 255 * 3 |
+---------+
|     765 |
+---------+
1 row in set (0.00 sec)

mysql&amp;gt; show create table areas;

CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `areaid` varchar(20) NOT NULL,
  `name` varchar(255) NOT NULL,
  `cityid` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_of_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3145 DEFAULT CHARSET=utf8 |

mysql&amp;gt; alter table areas change `name` `name` varchar(256) not null;
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
mysql&amp;gt; alter table areas drop index `idx_of_name`;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&amp;gt; alter table areas change `name` `name` varchar(256) not null;
Query OK, 3144 rows affected (0.06 sec)
Records: 3144  Duplicates: 0  Warnings: 0

mysql&amp;gt; show create table areas;

CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `areaid` varchar(20) NOT NULL,
  `name` varchar(256) NOT NULL,
  `cityid` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3145 DEFAULT CHARSET=utf8

mysql&amp;gt; alter table areas add index `idx_of_name` (name);
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加索引时，如果不指定索引的长度，MySQL 默认会选择该字段的长度作为索引长度。其实这里 &lt;/p&gt;

&lt;p&gt;alter table areas add index &lt;code&gt;idx_of_name&lt;/code&gt; (name)
    等同于
    alter table areas add index &lt;code&gt;idx_of_name&lt;/code&gt; (name(256))&lt;/p&gt;

&lt;p&gt;MySQL 索引最大 bytes 为 767， &lt;code&gt;255 * 3 &amp;lt; 767&lt;/code&gt; 但是 &lt;code&gt;256 * 3 &amp;gt; 767&lt;/code&gt; 所以，varchar(255) 时候，创建默认索引可以成功，但是 varchar(256) 时，创建默认索引就不成功。&lt;/p&gt;

&lt;p&gt;并且由上述列子可知，索引和字段相互影响，当索引设置为 &lt;code&gt;idx_of_name&lt;/code&gt; &lt;code&gt;(name(255))&lt;/code&gt;时，要改变字段的长度，也会提示 &lt;code&gt;Specified key was too long&lt;/code&gt; 错误。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;根据具体的业务需求来选择索引，并不是索引都会加快查询速度。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://www.jianshu.com/p/85a18c1e7d41" rel="nofollow" target="_blank" title=""&gt;我的简书&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.cnblogs.com/fullsail/archive/2013/05/18/3086286.html" rel="nofollow" target="_blank" title=""&gt;错误使用 MySQL 前缀索引导致的慢查询&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.cnblogs.com/weisenz/archive/2012/10/15/2724024.html" rel="nofollow" target="_blank" title=""&gt;MySQL 前缀索引&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.2cto.com/database/201302/188193.html" rel="nofollow" target="_blank" title=""&gt;mysql 前缀索引&lt;/a&gt;&lt;br&gt;
&lt;a href="http://blog.csdn.net/wyyl1/article/details/4171567" rel="nofollow" target="_blank" title=""&gt;mysql 省市区邮政编码和区号级联 sql 文件&lt;/a&gt;  &lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 21 Jul 2015 08:20:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/26580</link>
      <guid>https://ruby-china.org/topics/26580</guid>
    </item>
    <item>
      <title>MySQL 为什么需要一个主键</title>
      <description>&lt;h4 id="主键"&gt;主键&lt;/h4&gt;
&lt;p&gt;表中每一行都应该有可以唯一标识自己的一列（或一组列）。&lt;/p&gt;

&lt;p&gt;一个顾客可以使用顾客编号列，而订单可以使用订单 ID，雇员可以使用雇员 ID 或 雇员社会保险号。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;主键（primary key）一列（或一组列）&lt;/strong&gt;，其值能够唯一区分表中的每个行。
唯一标识表中每行的这个列（或这组列）称为主键。&lt;strong&gt;&lt;em&gt;没有主键，更新或删除表中特定行很困难，因为没有安全的方法保证只设计相关的行。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;虽然并不总是都需要主键，但大多数数据库设计人员都应保证他们创建的每个表有一个主键，以便于以后数据操纵和管理&lt;/p&gt;

&lt;p&gt;表中的任何列都可以作为主键，只要它满足一下条件：&lt;/p&gt;

&lt;p&gt;1、任何两行都不具有相同的主键值
     2、每个行都必须具有一个主键值（主键列不允许 NULL 值）&lt;/p&gt;

&lt;p&gt;主键值规范：这里列出的规则是 MySQL 本身强制实施的。&lt;/p&gt;

&lt;p&gt;主键的最好习惯：
     除 MySQL 强制实施的规则外，应该坚持的几个普遍认为的最好习惯为：&lt;/p&gt;

&lt;p&gt;1、不更新主键列的值
     2、不重用主键列的值
     3、不在主键列中使用可能会更改的值（例如，如果使用一个名字作为主键以标识某个供应商，应该供应商合并和更改其名字时，必须更改这个主键）&lt;/p&gt;

&lt;p&gt;总之：不应该使用一个具有意义的 column（id 本身并不保存表 有意义信息）作为主键，并且一个表必须要有一个主键，为方便扩展、松耦合，高可用的系统做铺垫。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;非常感谢 &lt;a href="/pathbox" class="user-mention" title="@pathbox"&gt;&lt;i&gt;@&lt;/i&gt;pathbox&lt;/a&gt;、 &lt;a href="/est" class="user-mention" title="@est"&gt;&lt;i&gt;@&lt;/i&gt;est&lt;/a&gt;、&lt;a href="/hooooopo" class="user-mention" title="@hooooopo"&gt;&lt;i&gt;@&lt;/i&gt;hooooopo&lt;/a&gt; 同学的提醒。主键的作用，在于索引。  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;无特殊需求下 Innodb 建议使用与业务无关的自增 ID 作为主键&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;InnoDB 引擎使用聚集索引，数据记录本身被存于主索引（一颗 B+Tree）的叶子节点上。&lt;strong&gt;这就要求同一个叶子节点内（大小为一个内存页或磁盘页）的各条数据记录按主键顺序存放&lt;/strong&gt;，因此每当有一条新的记录插入时，MySQL 会根据其主键将其插入适当的节点和位置，如果页面达到装载因子（InnoDB 默认为 15/16），&lt;strong&gt;则开辟一个新的页（节点）&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1、如果表使用自增主键，那么每次插入新的记录，记录就会顺序添加到当前索引节点的后续位置，当一页写满，就会自动开辟一个新的页。如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/primary_key_1.jpg" title="" alt=""&gt;  &lt;/p&gt;

&lt;p&gt;这样就会形成一个紧凑的索引结构，近似顺序填满。&lt;strong&gt;由于每次插入时也不需要移动已有数据，因此效率很高，也不会增加很多开销在维护索引上。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2、如果使用非自增主键（如果身份证号或学号等），由于每次插入主键的值近似于随机，因此每次新纪录都要被插到现有索引页得中间某个位置：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/primary_key_2.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;此时 MySQL 不得不为了将新记录插到合适位置而移动数据，甚至目标页面可能已经被回写到磁盘上而从缓存中清掉，此时又要从磁盘上读回来，这增加了很多开销，同时频繁的移动、分页操作造成了大量的碎片&lt;/strong&gt;，得到了不够紧凑的索引结构，后续不得不通过 OPTIMIZE TABLE 来重建表并优化填充页面。&lt;/p&gt;

&lt;p&gt;在使用 InnoDB 存储引擎时，如果没有特别的需要，请永远使用一个与业务无关的自增字段作为主键。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;InnoDB 存储引擎采用了聚集（clustered）的方式，因此每张表的存储都是按主键的顺序进行存放。如果没有显式地在表定义时指定主键，InnoDB 存储引擎会为每一行生成一个 6 字节的 ROWID，并一次作为主键。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mysql 在频繁的更新、删除操作，会产生碎片。而含碎片比较大的表，查询效率会降低。此时需对表进行优化，这样才会使查询变得更有效率。&lt;/strong&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;非常感谢 &lt;a href="/xiaoronglv" class="user-mention" title="@xiaoronglv"&gt;&lt;i&gt;@&lt;/i&gt;xiaoronglv&lt;/a&gt; 同学&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not define a PRIMARY KEY for your table, MySQL picks the first UNIQUE index that has only NOT NULL columns as the primary key and InnoDB uses it as the clustered index.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html" rel="nofollow" target="_blank" title=""&gt;具体参考 14.2.10.1 Clustered and Secondary Indexes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jianshu.com/p/66351fa26cd9" rel="nofollow" target="_blank" title=""&gt;我的简书&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 07 Jul 2015 08:05:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/26352</link>
      <guid>https://ruby-china.org/topics/26352</guid>
    </item>
    <item>
      <title>吞吐率、吞吐量、TPS、性能测试，纸上不谈兵 ---- 一步一步构建高性能 Web 站点</title>
      <description>&lt;h4 id="一、吞吐率"&gt;一、吞吐率&lt;/h4&gt;
&lt;p&gt;我们一般使用单位时间内服务器处理的请求数来描述其并发处理能力。称之为吞吐率（Throughput），单位是“req/s”。&lt;strong&gt;吞吐率特指 Web 服务器单位时间内处理的请求数。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;比如 Apache 的 mod_status 模块提供的如下统计&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_1.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;另一种描述，吞吐率是，单位时间内网络上传输的数据量，也可以指单位时间内处理客户请求数量。它是衡量网络性能的重要指标。通常情况下，吞吐率“字节数/秒”来衡量。当然你也可以用“请求数/秒”和“页面数/秒”来衡量。其实不管一个请求还是一个页面，它的本质都是在网络上传输的数据，那么用来表述数据的单位就是字节数。&lt;/p&gt;
&lt;h4 id="二、吞吐量"&gt;二、吞吐量&lt;/h4&gt;
&lt;p&gt;吞吐量，是指在一次性能测试过程中网络上传输的数据量的总和。&lt;/p&gt;

&lt;p&gt;  对于交互式应用来说，吞吐量指标反映的是服务器承受的压力，在容量规划的测试中，吞吐量是一个重点关注的指标，因为它能够说明系统级别的负载能力，另外，在性能调优过程中，吞吐量指标也有重要的价值。如一个大型工厂，他们的生产效率与生产速度很快，一天生产 10W 吨的货物，结果工厂的运输能力不行，就两辆小型三轮车一天拉 2 吨的货物，比喻有些夸张，但我想说明的是这个运输能力是整个系统的瓶颈。&lt;/p&gt;

&lt;p&gt;  提示，用吞吐量来衡量一个系统的输出能力是极其不准确的，用个最简单的例子说明，一个水龙头开一天一夜，流出 10 吨水；10 个水龙头开 1 秒钟，流出 0.1 吨水。当然是一个水龙头的吞吐量大。你能说 1 个水龙头的出水能力是 10 个水龙头的强？所以，我们要加单位时间，看谁 1 秒钟的出水量大。这就是吞吐率。&lt;/p&gt;
&lt;h4 id="三、事务，TPS(Transaction Per second)"&gt;三、事务，TPS(Transaction Per second)&lt;/h4&gt;
&lt;p&gt;就是用户某一步或几步操作的集合。不过，我们要保证它有一个完整意义。比如用户对某一个页面的一次请求，用户对某系统的一次登录，淘宝用户对商品的一次确认支付过程。这些我们都可以看作一个事务。那么如何衡量服务器对事务的处理能力。又引出一个概念----TPS&lt;/p&gt;

&lt;p&gt;每秒钟系统能够处理事务或交易的数量，它是衡量系统处理能力的重要指标。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;点击率可以看做是 TPS 的一种特定情况&lt;/strong&gt;。点击率更能体现用户端对服务器的压力。TPS 更能体现服务器对客户请求的处理能力。&lt;/p&gt;

&lt;p&gt;每秒钟用户向 web 服务器提交的 HTTP 请求数。这个指标是 web 应用特有的一个指标；web 应用是“请求 - 响应”模式，用户发一个申请，服务器就要处理一次，所以点击是 web 应用能够处理的交易的最小单位。&lt;strong&gt;如果把每次点击定义为一个交易，点击率和 TPS 就是一个概念。&lt;/strong&gt;容易看出，点击率越大。对服务器的压力也越大，点击率只是一个性能参考指标，重要的是分析点击时产生的影响。&lt;/p&gt;

&lt;p&gt;需要注意的是，这里的点击不是指鼠标的一次“单击”操作，因为一次“单击”操作中，客户端可能向服务器发现多个 HTTP 请求。&lt;/p&gt;
&lt;h4 id="四、吞吐量、吞吐率的意义"&gt;四、吞吐量、吞吐率的意义&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;吞吐量的限制是性能瓶颈的一种重要表现形式，因此，有针对地对吞吐量设计测试，可以协助尽快定位到性能冰晶所在的位置&lt;/li&gt;
&lt;li&gt;80% 系统的性能瓶颈都是由吞吐量制约&lt;/li&gt;
&lt;li&gt;并发用户和吞吐量瓶颈之间存在一定的关联&lt;/li&gt;
&lt;li&gt;通过不断增加并发用户数和吞吐量观察系统的性能瓶颈。然后，从网络、数据库、应用服务器和代码本身 4 个环节确定系统的性能瓶颈。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="五、吞吐率和压力测试"&gt;五、吞吐率和压力测试&lt;/h4&gt;
&lt;p&gt;单从定义来看，吞吐率描述了服务器在实际运行期间单位时间内处理的请求数，然而，我们更加关心的是&lt;code&gt;服务器并发处理能力的上限&lt;/code&gt;，也就是单位时间内服务器能够处理的最大请求数，即最大吞吐率。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;所以我们普遍使用“压力测试”的方法，通过模拟足够多数目的并发用户，分别持续发送一定的 HTTP 请求，并统计测试持续的总时间，计算出基于这种“压力”下的吞吐率，即为一个平均计算值&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;！！注意&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在 Web 服务器的实际工作中，其处理的 HTTP 请求通常包括对很多不同资源的请求，也就是请求不同的 URL，
比如这些请求有的是获取图片，有的是获取动态内容，显然服务器处理这些请求所花费的时间各不相同，而这些请求的不同时间组成比例又是不确定的。这就是实际情况下的吞吐率。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;所以，我们 对于同一个特定有代表性的请求进行压力测试，然后对多个请求的吞吐率按照比例计算加权平均值。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web 服务器并发能力强弱的关键便是在于如何计算针对不同的请求性质来设计最优并发策略。在一定程度上使得 Web 服务器的性能无法充分发挥，这很容易理解，就像银行对不同业务设立不同的窗口一样，这些窗口的服务员分别熟悉自己的窗口业务。可以未不同的客户分别快速办理业务，但是如果让这些窗口都可以办理所有业务，也就是客户可以去任何窗口办理任何业务，那会是怎么样呢？没有几个银行业务员会对所有业务都轻车熟路，这样势必会影响到整体的业务办理速度。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="六、压力测试的前提"&gt;六、压力测试的前提&lt;/h4&gt;
&lt;p&gt;吞吐率性能测试的前提&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;并发用户数&lt;/li&gt;
&lt;li&gt;总请求数&lt;/li&gt;
&lt;li&gt;请求资源描述&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;压力测试的描述一般包括两个部分，即并发用户数和总请求数，也就是模拟多少用户同时向服务器发送多少请求。&lt;/p&gt;

&lt;p&gt;请求性质则是对请求的 URL 所代表的资源的描述，比如 1KB 大小的静态文件，或者包含 10 次数据库查询的动态内容等。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1、并发用户数&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;并发用户数就是指在某一时刻同时向服务器发送请求的用户总数。&lt;/p&gt;

&lt;p&gt;假如 100 个用户同时向服务器分别进行 10 次请求，与 1 个用户向服务器连续进行 1000 次请求。两个的效果一样么？&lt;/p&gt;

&lt;p&gt;一个用户向服务器连续进行 1000 次请求的过程中，任何时刻服务器的网卡接受缓存区中只有来自该用户的 1 个请求，而 100 个用户同时向服务器分别进行 10 次请求的过程中，&lt;strong&gt;服务器网卡接收缓冲区中最多有 100 个等待处理的请求，显然这时候服务器的压力更大。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;经常有人说某个 Web 服务器能支持多少并发数，除此之外没有任何上下文，这让很多人摸不着头脑，人们常常把并发用户数和吞吐率混淆，他们并不是一回事。&lt;/p&gt;

&lt;p&gt;一个服务器最多支持多少并发用户数呢？&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web2.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;我们可以说，&lt;strong&gt;这个柜台支持的最大并发数为 10&lt;/strong&gt;，因为恰好在这个并发数下，柜台业务开展的非常成功。顾客们都对服务时间非常满意，而此时代表业务办理次数的柜台吞吐率也比较高，商场和顾客们实现双赢。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;可见，通常所讲的最大并发数是有一定利益前提的，那就是服务器和用户双方所期待的最大收益，服务器希望支持高并发数及高吞吐率，而用户不管那么多，只希望等待较少的时间，或者得到更快的下载速度。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;所以得出最大并发数的意义，在于了解服务器的承载能力，并且结合用户规模考虑适当的扩展方案。&lt;/p&gt;

&lt;p&gt;对于同一域名下 URL 的并发下载数是有最大限制的，具体限制视浏览器的不同而不同。
一个真实的用户可能会给服务器带来两个或更多的并发用户的压力，一些高明的用户还可以通过一些方法来修改浏览器的并发数限制。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_3.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_4.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2、请求等待时间&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;用户平均请求等待时间&lt;/li&gt;
&lt;li&gt;服务器平均请求处理时间&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;用户平均请求等待时间主要用户衡量服务器在一定并发用户数的情况下，对于单个用户的服务质量
服务器平均请求处理时间与前者相比，则用户衡量服务器的整体服务质量，它其实就是吞吐率的倒数。&lt;/p&gt;
&lt;h4 id="七、压力测试"&gt;七、压力测试&lt;/h4&gt;
&lt;p&gt;Apache 附带的 ab，ab 可以直接在 web 服务器本地发起测试请求。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_5.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1、吞吐率随并发用户数变化的曲线图&lt;/strong&gt;
&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_6.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2、服务器平均请求处理时间随并发用户数变化的曲线图&lt;/strong&gt;&lt;br&gt;
  当并发用户数超过 150 之后，请求的平均等待时间大幅度增加，当并发用户达到 200 后，等待时间开始急剧增加。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_7.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3、用户平均请求等待时间随并发用户数变化的曲线图&lt;/strong&gt;
&lt;img src="http://7ktwa5.com1.z0.glb.clouddn.com/web_8.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h4 id="八、总结"&gt;八、总结&lt;/h4&gt;
&lt;p&gt;针对，吞吐量，吞吐率，TPS 的测试，都需要指明单位时间。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;以上测试忽略服务器硬件配置，所以性能测试结果也不侧重于它的绝对值意义，我们的目的是探讨如何测量性能以及如何根据不同的场景来优化性能。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;以上测试使用硬件为&lt;/p&gt;

&lt;p&gt;CPU: Intel(R) Xeon(R) CPU 1.60GHz
    内存：4GB
    硬盘转速：15kr/min&lt;/p&gt;

&lt;p&gt;以上几个指标的测试，主要是为了提升服务器的处理效率，为构建高可用的 Web 站点做准备。&lt;/p&gt;
&lt;h4 id="九、下期内容"&gt;九、下期内容&lt;/h4&gt;
&lt;p&gt;影响 吞吐量，吞吐率，TPS 指标的因素，除了服务器的硬件配置，就剩下并发策略了。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;简单地说，并发策略的设计就是在服务器同时处理较多请求的时候，如何合理协调并充分利用 CPU 计算和 I/O 请求，使其在较大并发用户数的情况下提供较高的吞吐率&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;并不存在一个对所有性质的请求都高效的并发策略&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如需知道更多，请听下回分解。&lt;/p&gt;

&lt;p&gt;参考：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jianshu.com/users/4yjkua/latest_articles" rel="nofollow" target="_blank" title=""&gt;我的简书&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.cnblogs.com/fnng/archive/2012/06/29/2570558.html" rel="nofollow" target="_blank" title=""&gt;性能测试知多少--吞吐量&lt;/a&gt;&lt;br&gt;
&lt;a href="http://item.jd.com/11039445.html" rel="nofollow" target="_blank" title=""&gt;构建高性能 Web 站点&lt;/a&gt;  &lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Mon, 29 Jun 2015 05:58:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/26221</link>
      <guid>https://ruby-china.org/topics/26221</guid>
    </item>
    <item>
      <title>git cherry-pick 最佳实践</title>
      <description>&lt;h4 id="引题"&gt;引题&lt;/h4&gt;
&lt;p&gt;最近公司项目，成都小伙伴，在&lt;code&gt;develop&lt;/code&gt;上合并了错误的代码。
然后我们自己的分支上也合并了错误的代码。虽然最终&lt;code&gt;develop&lt;/code&gt;的代码回滚了，
错误的代码丢掉，但是自己分支上错误的提交还在，创建&lt;code&gt;merge request&lt;/code&gt; 的时，发现一大堆不是自己写的代码，如何解决呢？&lt;/p&gt;
&lt;h4 id="cherry-pick"&gt;cherry-pick&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;git-cherry-pick - Apply the changes introduced by some existing commits&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://git-scm.com/docs/git-cherry-pick" rel="nofollow" target="_blank" title=""&gt;git-scm#cherry-pick&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;拙略的英文，翻译为：可以把已经存在提交再次提交。&lt;/p&gt;
&lt;h4 id="实战"&gt;实战&lt;/h4&gt;
&lt;p&gt;总体思路如下：找到自己本工单号，本分支提交的&lt;code&gt;commits&lt;/code&gt;，在新分值上&lt;code&gt;merge&lt;/code&gt;这些&lt;code&gt;commits&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/cherry-pick-nnn.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第一步：&lt;/strong&gt; 格式化输出 log&lt;/p&gt;

&lt;p&gt;git log 命令可一接受一个--pretty 选项，来确定输出的格式.
如果我们只想输出 hash.&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git log --pretty=format:"%h" 

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git 用各种 placeholder 来决定各种显示内容：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;%H: commit hash&lt;/li&gt;
&lt;li&gt;%h: 缩短的 commit hash&lt;/li&gt;
&lt;li&gt;%T: tree hash&lt;/li&gt;
&lt;li&gt;%t: 缩短的 tree hash&lt;/li&gt;
&lt;li&gt;%P: parent hashes&lt;/li&gt;
&lt;li&gt;%p: 缩短的 parent hashes&lt;/li&gt;
&lt;li&gt;%an: 作者名字&lt;/li&gt;
&lt;li&gt;%aN: mailmap 的作者名字 (.mailmap 对应，详情参照 git-shortlog(1) 或者 git-blame(1))&lt;/li&gt;
&lt;li&gt;%ae: 作者邮箱&lt;/li&gt;
&lt;li&gt;%aE: 作者邮箱 (.mailmap 对应，详情参照 git-shortlog(1) 或者 git-blame(1))&lt;/li&gt;
&lt;li&gt;%ad: 日期 (--date= 制定的格式)&lt;/li&gt;
&lt;li&gt;%aD: 日期，RFC2822 格式&lt;/li&gt;
&lt;li&gt;%ar: 日期，相对格式 (1 day ago)&lt;/li&gt;
&lt;li&gt;%at: 日期，UNIX timestamp&lt;/li&gt;
&lt;li&gt;%ai: 日期，ISO 8601 格式&lt;/li&gt;
&lt;li&gt;%cn: 提交者名字&lt;/li&gt;
&lt;li&gt;%cN: 提交者名字 (.mailmap 对应，详情参照 git-shortlog(1) 或者 git-blame(1))&lt;/li&gt;
&lt;li&gt;%ce: 提交者 email&lt;/li&gt;
&lt;li&gt;%cE: 提交者 email (.mailmap 对应，详情参照 git-shortlog(1) 或者 git-blame(1))&lt;/li&gt;
&lt;li&gt;%cd: 提交日期 (--date= 制定的格式)&lt;/li&gt;
&lt;li&gt;%cD: 提交日期，RFC2822 格式&lt;/li&gt;
&lt;li&gt;%cr: 提交日期，相对格式 (1 day ago)&lt;/li&gt;
&lt;li&gt;%ct: 提交日期，UNIX timestamp&lt;/li&gt;
&lt;li&gt;%ci: 提交日期，ISO 8601 格式&lt;/li&gt;
&lt;li&gt;%d: ref 名称&lt;/li&gt;
&lt;li&gt;%e: encoding&lt;/li&gt;
&lt;li&gt;%s: commit 信息标题&lt;/li&gt;
&lt;li&gt;%f: sanitized subject line, suitable for a filename&lt;/li&gt;
&lt;li&gt;%b: commit 信息内容&lt;/li&gt;
&lt;li&gt;%N: commit notes&lt;/li&gt;
&lt;li&gt;%gD: reflog selector, e.g., refs/stash@{1}&lt;/li&gt;
&lt;li&gt;%gd: shortened reflog selector, e.g., stash@{1}&lt;/li&gt;
&lt;li&gt;%gs: reflog subject&lt;/li&gt;
&lt;li&gt;%Cred: 切换到红色&lt;/li&gt;
&lt;li&gt;%Cgreen: 切换到绿色&lt;/li&gt;
&lt;li&gt;%Cblue: 切换到蓝色&lt;/li&gt;
&lt;li&gt;%Creset: 重设颜色&lt;/li&gt;
&lt;li&gt;%C(...): 制定颜色，as described in color.branch.* config option&lt;/li&gt;
&lt;li&gt;%m: left, right or boundary mark&lt;/li&gt;
&lt;li&gt;%n: 换行&lt;/li&gt;
&lt;li&gt;%%: a raw %&lt;/li&gt;
&lt;li&gt;%x00: print a byte from a hex code&lt;/li&gt;
&lt;li&gt;%w([[,[,]]]): switch line wrapping, like the -w option of git-shortlog(1).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;第二步：&lt;/strong&gt; 根据需要输出自己的 commit&lt;/p&gt;

&lt;p&gt;根据上述 format，定制&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git log -150 --pretty=format:"%h %s %an %aD " | grep wanghao | grep xxxxx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 -150 表示输出 150 次的&lt;code&gt;commits&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;-&amp;lt;1number&amp;gt;, -n &amp;lt;1number&amp;gt;, --max-count=&amp;lt;1number&amp;gt;&lt;br&gt;
          Limit the number of commits to output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;%h : 缩短的 commit hash&lt;/li&gt;
&lt;li&gt;%s : commit 信息标题&lt;/li&gt;
&lt;li&gt;%an : 作者名字&lt;/li&gt;
&lt;li&gt;%aD : 日期，RFC2822 格式&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;grep wanghao grep xxxxx&lt;/code&gt; 管道符输出 &lt;/p&gt;

&lt;p&gt;是 wanghao 并且是工单 xxxxx 的 commits&lt;/p&gt;

&lt;p&gt;最终输出如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;98743af [rmxxxxx] Merge branch 'develop' xxxxx
2b48938 [rmxxxxx] rmxxxxxx wanghao 
3320829 [rmxxxxx] rmxxxxxx ****** wanghao Mon, 18 May 2015 14:42:51 +0800
1e09778 [rmxxxxx] rmxxxxxx ****** wanghao Sun, 17 May 2015 18:07:44 +0800

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;第三步：&lt;/strong&gt; 运用强大的 cherry-pick &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout develop
git pull origin develop
git checkout -b feature/rmxxxxx_wanghao_20150521_xxxx
git cherry-pick 2b48938 3320829 1e09778
git branch -D feature/rmxxxxx_wanghao_20150521_xxxx_tmp

git push origin :feature/rmxxxxx_wanghao_20150521_xxxx
git push origin feature/rmxxxxx_wanghao_20150521_xxxx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;bingo!&lt;/p&gt;

&lt;p&gt;参考：&lt;br&gt;
&lt;a href="https://ruby-china.org/topics/939" title=""&gt;ruby-china#个性化你的Git log 输出格式&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Thu, 21 May 2015 06:01:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/25676</link>
      <guid>https://ruby-china.org/topics/25676</guid>
    </item>
    <item>
      <title>MySQL 数据库 varchar 到底可以存多少个汉字，多少个英文呢?我们来搞搞清楚</title>
      <description>&lt;h4 id="一、关于UTF-8"&gt;一、关于 UTF-8&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;UTF-8&lt;/code&gt; Unicode Transformation Format-8bit。是用以解决国际上字符的一种多字节编码。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;它对英文使用 8 位（即一个字节) ，中文使用 24 位（三个字节）来编码。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;UTF-8&lt;/code&gt;包含全世界所有国家需要用到的字符，是国际编码，通用性强。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UTF-8&lt;/code&gt;编码的文字可以在各国支持 UTF8 字符集额的浏览器上显示。
如果是&lt;code&gt;UTF8&lt;/code&gt;编码，则在外国人的英文 IE 也能显示中文，他们无需下载 IE 的中文语言支持包。&lt;/p&gt;
&lt;h4 id="二、关于GBK"&gt;二、关于 GBK&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;GBK&lt;/code&gt; 是国家标准 GB2312 基础上扩容后兼容 GB2312 的标准。&lt;br&gt;
&lt;code&gt;GBK&lt;/code&gt;的文字编码是用双字节来表示的，即不论中、英文字符均使用双字节来表示，为了区分中文，将其最高位都设定成 1。&lt;br&gt;
&lt;code&gt;GBK&lt;/code&gt;包含全部中文字符，是国家编码，通用性比 UTF8 差，不过 UTF8 占用的数据库比&lt;code&gt;GBK&lt;/code&gt;大。&lt;/p&gt;
&lt;h4 id="三、关于utf8mb4"&gt;三、关于 utf8mb4&lt;/h4&gt;
&lt;p&gt;MySql 5.5 之前，UTF8 编码只支持 1-3 个字节，只支持 BMP 这部分的 unicode 编码区，BMP 是从哪到哪？
&lt;a href="http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters" rel="nofollow" target="_blank" title=""&gt;戳这里&lt;/a&gt; 基本就是 0000 ~ FFFF 这一区。&lt;/p&gt;

&lt;p&gt;从 MySQL 5.5 开始，可支持 4 个字节 UTF 编码 utf8mb4，一个字符最多能有 4 字节，所以能支持更多的字符集。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
    utf8mb4 is a superset of utf8
&lt;/code&gt;   &lt;/p&gt;

&lt;p&gt;tf8mb4 兼容 utf8，且比 utf8 能表示更多的字符。&lt;br&gt;
至于什么时候用，看你做的什么项目了。。。
在做移动应用时，会遇到&lt;code&gt;IOS&lt;/code&gt;用户在文本的区域输入&lt;code&gt;emoji&lt;/code&gt;表情，如果不做一定处理，就会导致插入数据库异常。&lt;/p&gt;
&lt;h4 id="四、汉字长度与编码有关"&gt;四、汉字长度与编码有关&lt;/h4&gt;
&lt;p&gt;MySql 5.0 以上的版本：&lt;/p&gt;

&lt;p&gt;1、一个汉字占多少长度与编码有关：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UTF-8：一个汉字 = 3 个字节，英文是一个字节&lt;/li&gt;
&lt;li&gt;GBK：一个汉字 = 2 个字节，英文是一个字节&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2、varchar(n) 表示 n 个字符，无论汉字和英文，&lt;code&gt;MySql&lt;/code&gt;都能存入 &lt;code&gt;n&lt;/code&gt; 个字符，仅实际字节长度有所区别。&lt;/p&gt;

&lt;p&gt;3、MySQL 检查长度，可用 SQL 语言&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
    SELECT LENGTH(fieldname) FROM tablename 
&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="五、实际测试"&gt;五、实际测试&lt;/h4&gt;
&lt;p&gt;1、首先使用&lt;code&gt;utf8&lt;/code&gt; 创建  &lt;code&gt;str_test&lt;/code&gt; 表。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE `str_test` (
    `name_chn` varchar(20) NOT NULL,
    `name_en`  varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后插入值&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; insert into  str_test values ('我爱Ruby', 'I Love Ruby!');
Query OK, 1 row affected (0.02 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打开 irb&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; "我爱Ruby".size
=&amp;gt; 6
&amp;gt;&amp;gt; "I Love Ruby!".size
=&amp;gt; 12
&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从 MySQL 中查询出来的结果，对比&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select * from str_test;
+------------+--------------+
| name_chn   | name_en      |
+------------+--------------+
| 我爱Ruby   | I Love Ruby! |
+------------+--------------+
1 row in set (0.02 sec)


mysql&amp;gt; select length(name_chn) from str_test;
+------------------+
| length(name_chn) |
+------------------+
|               10 |
+------------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3[一个汉字三字节] * 2 + 1[一个英文一字节] * 4 = 10&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select length(name_en) from str_test;
+-----------------+
| length(name_en) |
+-----------------+
|              12 |
+-----------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;10[一个英文一字节] * 1 + 2[空格一字节] * whitespace = 12&lt;/p&gt;

&lt;p&gt;2、使用 &lt;code&gt;GBK&lt;/code&gt; 做测试&lt;/p&gt;

&lt;p&gt;创建表&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    CREATE TABLE `str_test` (
    `name_chn` varchar(20) NOT NULL,
    `name_en`  varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;插入数据，并且测试&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; insert into  str_test values ('我爱Ruby', 'I Love Ruby!');
Query OK, 1 row affected (0.00 sec)

mysql&amp;gt; select * from str_test;
+------------+--------------+
| name_chn   | name_en      |
+------------+--------------+
| 我爱Ruby   | I Love Ruby! |
+------------+--------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;GBK&lt;/code&gt; 中文是两个字节，英文是一个字节。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select length(name_chn) from str_test;
+------------------+
| length(name_chn) |
+------------------+
|                8 |
+------------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2[中文两个字节] * 2 + 4[英文一个字节] * 1 = 8&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select length(name_en) from str_test;
+-----------------+
| length(name_en) |
+-----------------+
|              12 |
+-----------------+
1 row in set (0.00 sec)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;10[英文一个字节] * 1 + 2[空格一个字节] * whitespace = 12&lt;/p&gt;
&lt;h5 id="六、关于varchar 最多能存多少值"&gt;六、关于 varchar 最多能存多少值&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;mysql 的记录行长度是有限制的，不是无限长的，这个长度是&lt;code&gt;64K&lt;/code&gt;，即&lt;code&gt;65535&lt;/code&gt;个字节，对所有的表都是一样的。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MySQL 对于变长类型的字段会有 1-2 个字节来保存字符长度。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;当字符数小于等于 255 时，MySQL 只用 1 个字节来记录，因为 2 的 8 次方减 1 只能存到 255。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;当字符数多余 255 时，就得用 2 个字节来存长度了。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在&lt;code&gt;utf-8&lt;/code&gt;状态下的 varchar，最大只能到 (65535 - 2) / 3 = 21844 余 1。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在&lt;code&gt;gbk&lt;/code&gt;状态下的 varchar, 最大只能到 (65535 - 2) / 2 = 32766 余 1 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用 &lt;code&gt;utf-8&lt;/code&gt; 创建&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt;     CREATE TABLE `str_test` (
-&amp;gt;         `id`  tinyint(1)  NOT NULL,
-&amp;gt;         `name_chn` varchar(21845) NOT NULL
-&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
-&amp;gt; ;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql&amp;gt;     CREATE TABLE `str_test` (
-&amp;gt;         `id`  tinyint(1)  NOT NULL,
-&amp;gt;         `name_chn` varchar(21844) NOT NULL
-&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=utf8
-&amp;gt;
-&amp;gt;
-&amp;gt; ;
Query OK, 0 rows affected (0.06 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用&lt;code&gt;gbk&lt;/code&gt;创建&lt;/p&gt;

&lt;p&gt;当存储长度为 32768 失败~&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    mysql&amp;gt;     CREATE TABLE `str_test` (
    -&amp;gt;         `id`  tinyint(1)  NOT NULL,
    -&amp;gt;         `name_chn` varchar(32768) NOT NULL
    -&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
    -&amp;gt; ;
ERROR 1074 (42000): Column length too big for column 'name_chn' (max = 32767); use BLOB or TEXT instead
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当存储长度为 32767 失败~&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt;     CREATE TABLE `str_test` (                                                                                                 -&amp;gt;         `id`  tinyint(1)  NOT NULL,
    -&amp;gt;         `name_chn` varchar(32767) NOT NULL
    -&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
    -&amp;gt; ;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当存储长度为 32766 成功~&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt;     CREATE TABLE `str_test` (
    -&amp;gt;         `id`  tinyint(1)  NOT NULL,
    -&amp;gt;         `name_chn` varchar(32766) NOT NULL
    -&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
    -&amp;gt; ;
Query OK, 0 rows affected (0.03 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;smallint 用两个字节存储，所以 &lt;/p&gt;

&lt;p&gt;2[smallint] + 32766 * 2[varchar 存储长度] + 2[2 个字节来存长度] &amp;gt; 65535&lt;/p&gt;

&lt;p&gt;所以失败~&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt;     CREATE TABLE `str_test` (
    -&amp;gt;         `id`  smallint(1)  NOT NULL,
    -&amp;gt;         `name_chn` varchar(32766) NOT NULL
    -&amp;gt;     ) ENGINE=InnoDB AUTO_INCREMENT=62974 DEFAULT CHARSET=gbk
    -&amp;gt; ;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#####七、数值类型所占的字节&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;所占字节&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;4 字节&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;smallint&lt;/td&gt;
&lt;td&gt;2 字节&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tinyint&lt;/td&gt;
&lt;td&gt;1 字节&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;decimal&lt;/td&gt;
&lt;td&gt;变长&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;官方关于&lt;code&gt;decimal&lt;/code&gt; 的描述如下&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Values for DECIMAL (and NUMERIC) columns are represented using a binary format that packs nine decimal (base 10) digits into four bytes.&lt;br&gt;
Storage for the integer and fractional parts of each value are determined separately.&lt;br&gt;
Each multiple of nine digits requires four bytes, and the “leftover” digits require some fraction of four bytes.&lt;br&gt;
The storage required for excess digits is given by the following table. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;翻译为中文&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;使用二进制格式将 9 个十进制 (基于 10) 数压缩为 4 个字节来表示 DECIMAL 列值。&lt;br&gt;
每个值的整数和分数部分的存储分别确定。&lt;br&gt;
每个 9 位数的倍数需要 4 个字节，并且“剩余的”位需要 4 个字节的一部分。&lt;br&gt;
下表给出了超出位数的存储需求： &lt;/p&gt;
&lt;/blockquote&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Leftover Digits&lt;/th&gt;
&lt;th&gt;Number Of Bytes&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;那：decimal(10,2) 占几个字节？&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1、首先 10 指的是整数与小数部分的总长度，2 指的是小数部分的长度。那么整数部分就只有 10 - 2 = 8 位&lt;/p&gt;

&lt;p&gt;2、因为整数与小数的存储市各自独立确定的，所以他们各自所占用空间的综合就是所占的总空间了。&lt;/p&gt;

&lt;p&gt;3、对表可知，整数部分 8 位占了 4 个字节，小数部分 2 位占了 1 个字节，所以 decimal(10,2) 总共占了 4 + 1 = 5 个字节。&lt;/p&gt;

&lt;p&gt;4、decimal(6,2) 整数部分 (6 - 2 = 4) 位占 2 字节，小数部分 2 位占 1 字节，总共占 3 字节。&lt;/p&gt;
&lt;h5 id="八、总结"&gt;八、总结&lt;/h5&gt;
&lt;p&gt;varchar 字段是将实际内容单独存储在聚簇索引之外，内容开头用 1 到 2 个字节表示实际长度（长度超过 255 时需要 2 个字节），因此最大长度不能超过 65535。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UTF-8：一个汉字 = 3 个字节，英文是一个字节&lt;/li&gt;
&lt;li&gt;GBK：一个汉字 = 2 个字节，英文是一个字节&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在&lt;code&gt;utf-8&lt;/code&gt;状态下，汉字最多可以存 &lt;strong&gt;21844&lt;/strong&gt;个字符串，英文也为 &lt;strong&gt;21844&lt;/strong&gt;个字符串。&lt;/p&gt;

&lt;p&gt;在&lt;code&gt;gbk&lt;/code&gt;状态下，汉字最多可以存 &lt;strong&gt;32766&lt;/strong&gt;个字符串，英文也为 &lt;strong&gt;32766&lt;/strong&gt;个字符串。&lt;/p&gt;
&lt;h4 id="参考"&gt;参考&lt;/h4&gt;
&lt;p&gt;&lt;a href="http://my.oschina.net/wingyiu/blog/153357" rel="nofollow" target="_blank" title=""&gt;mysql utf8mb4 与 emoji 表情&lt;/a&gt;&lt;br&gt;
&lt;a href="http://csumissu.iteye.com/blog/1090053" rel="nofollow" target="_blank" title=""&gt;关于 GBK、GB2312、UTF8&lt;/a&gt;&lt;br&gt;
&lt;a href="https://importnew.com/topics/24693" rel="nofollow" target="_blank" title=""&gt;阿里云 Rails 项目调整 RDS MySQL 编码为 utf8mb4 的详细步骤&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.111cn.net/database/mysql/54999.htm" rel="nofollow" target="_blank" title=""&gt;MySQL 下 varchar 类型最大长度是多少&lt;/a&gt;&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 31 Mar 2015 08:47:30 +0800</pubDate>
      <link>https://ruby-china.org/topics/24920</link>
      <guid>https://ruby-china.org/topics/24920</guid>
    </item>
    <item>
      <title>关于数据库连接池的疑问</title>
      <description>&lt;p&gt;数据库连接池是一种昂贵的资源，创建和销毁都需要时间和资源。
所以通常设置数据库连接池最小连接，最大连接，用来缓存这种昂贵的资源。&lt;/p&gt;

&lt;p&gt;那么问题来了。&lt;/p&gt;

&lt;p&gt;如果当前，我有个应用，设置最小连接 10，最大连接 20
但系统中有每分钟的 100w pv，并且其中有大量的读写操作。&lt;/p&gt;

&lt;p&gt;通常是怎样解决这种问题？&lt;/p&gt;

&lt;p&gt;1、只有一台服务器，增大数据库连接？（如，将最小连接调教到 30，最大连接调教到 50）
2、增加服务器，使用 Nginx 代理？（每个服务器，最小连接为 10，最大连接为 20）
3、数据库连接池不够，是否是增加服务器的重要指标？
4、通常如何设定一台服务器合适的数据库连接呢？
5、实践中是否还有其他解决方案么？&lt;/p&gt;

&lt;p&gt;&lt;img src="http://g.hiphotos.baidu.com/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=cf6b48ea80025aafc73f76999a84c001/14ce36d3d539b600248b019deb50352ac65cb756.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;虚心请教各位大神。&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Mon, 23 Mar 2015 08:39:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/24788</link>
      <guid>https://ruby-china.org/topics/24788</guid>
    </item>
    <item>
      <title>新手做网站的准备，入门贴</title>
      <description>&lt;p&gt;正文&lt;/p&gt;
&lt;h2 id="一、网站前期的准备"&gt;一、网站前期的准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;   买域名&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   租服务器&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   编写网站代码&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;总体就这三步，但是每一点都有好多必须要要了解的地方。&lt;/p&gt;
&lt;h2 id="二、使用到的工具"&gt;二、使用到的工具&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;   新网域名服务&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   DNSpod&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   locvps&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   Bootstrap&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   nginx + mysql + ubuntu + rails&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   百度网盘，七牛云存储&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;最终的效果图&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/BA66904B-B2CA-4745-95F5-C6A2F13D1C66.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="三、疑问？"&gt;三、疑问？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;   如何购买域名？购买什么域名比较好？域名多少钱？&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   如何租用服务器？国内的服务器和国外的服务器又什么区别？&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   如何绑定域名和 IP 地址呢？&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   我不会 CSS，如何写出漂亮的界面？&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="四、为啥要购买域名呢？"&gt;四、为啥要购买域名呢？&lt;/h2&gt;
&lt;p&gt;举个例子，每个人出生的时候，都会有一串数字，这串数字会更随着你一生。它就是身份证，&lt;code&gt;14xxxxxxxxxxxxxxxxxx&lt;/code&gt;。&lt;strong&gt;这串数字是你在地球上生活的的唯一标识符。&lt;/strong&gt;  但是考虑到它的实用性，父母叫你的时候不可能叫你的身份证号吧，所以就给你起了个名字。&lt;code&gt;狗蛋儿&lt;/code&gt;。&lt;br&gt;
&lt;code&gt;狗蛋儿&lt;/code&gt;对应的就是 &lt;code&gt;14xxxxxxxxxxxxxxxxxx&lt;/code&gt;。上学同学叫你&lt;code&gt;狗蛋儿&lt;/code&gt;，老师叫你&lt;code&gt;狗蛋儿&lt;/code&gt;，女朋友叫你&lt;code&gt;狗蛋儿&lt;/code&gt;。别人只需要知道你的名字就好了，不需要知道你的身份证是多少。&lt;/p&gt;

&lt;p&gt;在互联网中，每个机器设备都会有唯一的标识符，IP 地址。但是记忆 IP 地址太不靠谱了，所以有人就想了个招，给它起个名字吧。&lt;/p&gt;

&lt;p&gt;如，办一个公司，买一个一个公网服务器，就有了公网的 IP 地址（就相当于有了个儿子，儿子有了身份证号），但是想让外面的人知道，就向域名服务商购买域名（给儿子起了个名字）将域名和购买的公网 IP 地址绑定（公安局办户口），两者就关联在一起了。&lt;/p&gt;
&lt;h2 id="五、如何购买域名？"&gt;五、如何购买域名？&lt;/h2&gt;
&lt;p&gt;国内的著名域名提供商有新网、万网。&lt;br&gt;
由于楼主一直使用新网的域名服务，所以这里推荐&lt;a href="http://www.xinnet.com/" rel="nofollow" target="_blank" title=""&gt;新网&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;购买域名之前，简单介绍下域名的种类和一些特性  &lt;/p&gt;
&lt;h4 id="1、com域名"&gt;1、com 域名&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;   英文名 company。&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;.com&lt;/code&gt;是目前国际最广泛流行的通用域名格式。&lt;/li&gt;
&lt;li&gt;   com 为 company 简称，表示公司企业。&lt;code&gt;.com&lt;/code&gt;是目前国际最广泛流行的通用域名格式，现全球的用户超过 1.1 亿个。所有国际化公司都会注册&lt;code&gt;.com&lt;/code&gt;域名。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;.com&lt;/code&gt;域名的在互联网域名系统是一个顶级域名 (TLD) 。 &lt;/li&gt;
&lt;li&gt;   如果做 SEO 优化，及谷歌广告推广等使用，请使用&lt;code&gt;com域名&lt;/code&gt;,&lt;code&gt;cn&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;域名，这些域名在搜索中权重较高。如果你注册一个后缀是&lt;code&gt;xx&lt;/code&gt;的域名，别人的一看便是非法网站，就没兴趣浏览了。&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2、org域名"&gt;2、org 域名&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;   英文名 organization。&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;.org&lt;/code&gt;适用于各类组织机构，包括非盈利团体。在注册方面，org 域名的资格没有任何限制，任何一个国家的个人或企业均可注册。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;.org&lt;/code&gt;域名与&lt;code&gt;·com&lt;/code&gt;和&lt;code&gt;·net&lt;/code&gt;同是目前国际最广泛流行的通用域名格式。&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3、net域名"&gt;3、net 域名&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;   &lt;code&gt;.net&lt;/code&gt;是国际最广泛流行的通用域名格式。一般用于从事 Internet 相关的网络服务的机构或公司，是建立全球商业品牌，国际化形象的第一选择。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="4、me域名"&gt;4、me 域名&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;   &lt;code&gt;.me&lt;/code&gt;域名是欧洲西南部的国家黑山共和国（Montenegro，原为南斯拉夫社会主义联邦共和国的一部分，2006 年宣布独立）的国家域名。&lt;code&gt;.me&lt;/code&gt;域名是全球最新推出的顶级域名。&lt;/li&gt;
&lt;li&gt;   对注册&lt;code&gt;.me&lt;/code&gt;域名的资格没有任何限制，任何一个国家的个人或企业均可注册。虽然没有使用限制，但是在北京&lt;code&gt;.me&lt;/code&gt;域名，备案肯定会通不过。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;回到之前的问题。既然做了上面的介绍，推荐购买&lt;code&gt;.com&lt;/code&gt;域名。
域名一定要简单明了，比如百度 (baidu.com), 谷歌 (g.cn 谷歌中国域名),dota(dota.uuu9.com)，资料介绍，知名公司的网址的平均长度为 7.5。&lt;/p&gt;

&lt;p&gt;还有，域名中尽量不要添加“-”（中横线），因为会降低爬虫检索的权重。&lt;/p&gt;

&lt;p&gt;购买域名前，搜索自己心爱的域名是否被购买了。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/baidu_already_sold.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;综上所述，楼主购买了&lt;br&gt;
&lt;a href="http://www.le1024.com" rel="nofollow" target="_blank" title=""&gt;www.le1024.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;le 代表了 快乐，愉悦。
1024 所表达的含义，类似于“顶”、“非常棒”。&lt;/p&gt;

&lt;p&gt;网站的宗旨，&lt;code&gt;分享有趣，有爱，有故事&lt;/code&gt;的视频。&lt;/p&gt;
&lt;h2 id="六、如何挑选服务器"&gt;六、如何挑选服务器&lt;/h2&gt;&lt;h4 id="1、国内服务器推荐"&gt;1、国内服务器推荐&lt;/h4&gt;
&lt;p&gt;阿里云 (稳定，安全，服务好)，价格相对适中。
    双核，2G 内存，2M 带宽，20GB 固态硬盘  194RMB/每月。
    为啥推荐阿里云呢？因为阿里云提供备案服务，只需要提供身份证及网站负责人备案图片（阿里云与照相馆合作，免费拍照，费用阿里云出），资料准备好之后，最后提供给 ICP（因特网内容提供商英文全称为 Internet Content Provider）审核，等待审核之后，ICP 会短信通知你。&lt;/p&gt;

&lt;p&gt;国内播放视频，必须办理视频许可证。&lt;/p&gt;

&lt;p&gt;国内服务器优点：&lt;code&gt;速度快，网络相对稳定，选择阿里云，扩展比较方便&lt;/code&gt;  。
国内服务器缺点：&lt;code&gt;必须要备案，没有备案，域名不会解析到公网IP地址&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;注意：千万别相信，某宝上，一天快速备案的广告。&lt;/p&gt;

&lt;p&gt;吐槽一下，电视剧，电影有审核，制作网站也需要审核，屏蔽谷歌，facebook 等等，中国在文化上的闭关锁国上越走越远。&lt;/p&gt;

&lt;p&gt;其余的国内服务器没用过，不便瞎说。&lt;/p&gt;
&lt;h4 id="2、国外服务器推荐"&gt;2、国外服务器推荐&lt;/h4&gt;
&lt;p&gt;Linode：美国 VPS 提供商，专注于基于 XEN 虚拟的 VPS，成立于 2003 年，办公地点在新泽西。所提供的 VPS 服务颇多好评。但只支持信用卡这一种付款方式，在国内购买多有不便。最基本的服务方案是 Linode 1G，10$每月。&lt;/p&gt;

&lt;p&gt;locvps:  采用 Intel Xeon CPU，标准 1U 服务器，ECC 错误效验内存，G 口网络接入，Raid10+BBU 磁盘阵列，保障您的 VPS 稳定运行。
      CPU：2 CPUs 内存：512 M 硬盘：15 G 端口：2 M 流量：不限。&lt;/p&gt;

&lt;p&gt;楼主就使用的 locvps，原因，某运维推荐的。&lt;/p&gt;

&lt;p&gt;国外服务器优点：&lt;code&gt;不需要备案，限制少&lt;/code&gt;  。
国外服务器缺点：&lt;code&gt;速度略慢&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果你由于某些因素，不备案的话，选择国外服务器是不错的选择。&lt;/p&gt;
&lt;h2 id="七、 如何绑定域名和IP地址呢?"&gt;七、如何绑定域名和 IP 地址呢？&lt;/h2&gt;
&lt;p&gt;首先需要知道，
DNS（Domain Name System，域名系统），因特网上作为域名和 IP 地址相互映射的一个分布式数据库，能够使用户更方便的访问互联网，而不用去记住能够被机器直接读取的 IP 数串。通过主机名，最终得到该主机名对应的 IP 地址的过程叫做域名解析（或主机名解析）。&lt;/p&gt;

&lt;p&gt;在一个 TCP/IP 架构的网络（例如 Internet）环境中，DNS 是一个非常重要而且常用的系统。主要的功能就是将人易于记忆的 Domain Name 与人不容易记忆的 IP Address 作转换。而上面执行 DNS 服务的这台网络主机，就可以称之为 DNS Server。基本上，通常我们都认为 DNS 只是将 Domain Name 转换成 IP Address，然后再使用所查到的 IP Address 去连接（俗称“正向解析”）。事实上，将 IP Address 转换成 Domain Name 的功能也是相当常使用到的，当 login 到一台 Unix 工作站时，工作站就会去做反查，找出你是从哪个地方连线进来的（俗称“逆向解析”）。&lt;/p&gt;

&lt;p&gt;这里我们介绍下免费提供 DNS 解析的工具&lt;code&gt;DNSpod&lt;/code&gt;,&lt;code&gt;DNSPod&lt;/code&gt;是中国第一大 DNS 解析服务提供商、第一大域名托管商。它除了实时生效、不限制用户添加的域名和记录数量、提供 URL 转发、搜索引擎优化、域名共享管理、域名锁定、IPv6 的支持、动态域名解析、API 接口、批量修改管理等先进功能外，还拥有：云 DNS、DNSPod DNS Protector（DNSPod 自主研发的 DNS 防护软件）、宕机监控、安全中心、7*24 小时专业技术支持。并且所有功能都是免费向所有用户提供。&lt;/p&gt;

&lt;p&gt;新修改域名 DNS 指向 DNSPod 的 DNS 域名，虽 DNSPod 服务器的生效时间是实时的，&lt;code&gt;但因各地ISP服务商刷新域名DNS的时间不一致，所以导致解析在全球生效一般需要0--72小时&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;使用 DNSpod 解析域名，具体主要流程    &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;   在域名提供商管理后台，配置域名 DNS 为 DNSpod 提供的
&lt;code&gt;f1g1ns1.dnspod.net&lt;/code&gt;
&lt;code&gt;f1g1ns2.dnspod.net&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;具体操作如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;   登陆 &lt;a href="http://dcp.xinnet.com/Modules/agent/domain/domain_manage.jsp" rel="nofollow" target="_blank"&gt;http://dcp.xinnet.com/Modules/agent/domain/domain_manage.jsp&lt;/a&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   选择［域名管理］&lt;br&gt;
&lt;img src="https://statics.dnspod.cn/zhanjiang/images/about/support/1181.png" title="" alt=""&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   选择【域名状态设置】，先为域名解锁（否则无法修改 DNS）&lt;br&gt;
&lt;img src="https://statics.dnspod.cn/zhanjiang/images/about/support/1182.png" title="" alt=""&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   然后再选择【修改域名 DNS】&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   若【当前状态】中有状态信息，则将且所有状态移至【增加状态】栏内；继续操作步骤&lt;br&gt;
&lt;img src="https://statics.dnspod.cn/zhanjiang/images/about/support/1183.png" title="" alt=""&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;   DNS 地址修改完成后再将【域名状态设置】恢复原状。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;选择域名服务器为【填写具体信息】，修改域名 DNS 服务器为 DNSPod 的 2 个 DNS 短地址（对应 6 台服务器）&lt;br&gt;
&lt;code&gt;f1g1ns1.dnspod.net&lt;/code&gt;
&lt;code&gt;f1g1ns2.dnspod.net&lt;/code&gt;
&lt;img src="https://statics.dnspod.cn/zhanjiang/images/about/support/1184.png" title="" alt=""&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;点击保存，然后等待全球递归 DNS 服务器刷新（最多 72 小时）。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在 DNSpod 管理平台，设置域名，并解析到服务器 IP 地址&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如图&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/my_dnspod_le1024.jpg" title="" alt=""&gt;
DNSpod 设置完毕之后，最快当时便可以解析到 IP 地址。&lt;/p&gt;
&lt;h2 id="八、我不会CSS，如何写出漂亮的界面？"&gt;八、我不会 CSS，如何写出漂亮的界面？&lt;/h2&gt;
&lt;p&gt;我也不会写 css，我推荐 大名鼎鼎的 &lt;code&gt;Bootstrap&lt;/code&gt;  。
&lt;code&gt;Bootstrap&lt;/code&gt;是 Twitter 推出的一个开源的用于前端开发的工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发，是一个 CSS/HTML 框架。Bootstrap 提供了优雅的 HTML 和 CSS 规范，它即是由动态 CSS 语言 Less 写成。&lt;/p&gt;

&lt;p&gt;为所有开发者、所有应用场景而设计。
Bootstrap 让前端开发更快速、简单。所有开发者都能快速上手、所有设备都可以适配、所有项目都适用。&lt;/p&gt;

&lt;p&gt;Demo one&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/bootstrap1.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;Demo two&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/bootstrap2.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;需要深入了解的 Bootstrap 栅格系统&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/bootstrap4.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;其实 Bootstrap 还提供了好多实用的组件，如&lt;/p&gt;

&lt;p&gt;&lt;img src="http://happyforni.qiniudn.com/bootstrap3.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;自己琢磨下，研究研究，一定能写出漂亮的网页。&lt;/p&gt;
&lt;h2 id="九、 宣传语"&gt;九、宣传语&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.le1024.com" rel="nofollow" target="_blank" title=""&gt;le1024&lt;/a&gt; 每天推荐 1~3 段，有趣、有爱、有故事的视频。
为您工作、学习、生活之余增加一点快乐的感觉。
欢迎关注 happyforni 微信公众号。
你的开心快乐，就是我最重要的决定！&lt;/p&gt;
&lt;h2 id="十、服务器软件安装"&gt;十、服务器软件安装&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/languoliang/archive/2013/04/01/nginx.html" rel="nofollow" target="_blank" title=""&gt;ubuntu 安装 nginx&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.cnblogs.com/zhuyp1015/p/3561470.html" rel="nofollow" target="_blank" title=""&gt;ubuntu 安装 mysql&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ruby-china.org/wiki/install_ruby_guide" title=""&gt;ubuntu 安装 ruby 及 rails 环境&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;原标题，&lt;a href="http://www.jianshu.com/p/68768cd27125" rel="nofollow" target="_blank" title=""&gt;《我是如何在两天内做一个网站的》--简书&lt;/a&gt; 格式有修改，本人原创，转载至 ruby-china，欢迎各位大神批评、指正。&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Sun, 25 Jan 2015 18:06:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/23932</link>
      <guid>https://ruby-china.org/topics/23932</guid>
    </item>
    <item>
      <title>le1024、程序员不得不知的快乐视频网站</title>
      <description>&lt;p&gt;历经两个半月的准备，三次大改版，十七次小改版。le1024 终于要和大家见面了。
le1024 每天推荐 1~3 段，有趣、有爱、有故事的视频。
为您工作、学习、生活之余增加一点快乐的感觉。
百度或谷歌搜索 &lt;a href="http://www.le1024.com" rel="nofollow" target="_blank" title=""&gt;www.le1024.com&lt;/a&gt;, 或直接在浏览器输入上述地址。
欢迎关注 happyforni 微信公众号。
你的开心快乐，就是我最重要的决定！&lt;/p&gt;

&lt;p&gt;1、美女银行柜员，也是蛮拼的
&lt;img src="http://yannini.qiniudn.com/1100641F46541A34E91FF9139B1FA4C823E9CE-05A4-D1CC-5E73-38AD90CDD097.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;2、我只是和你讲一个关于青春的故事
&lt;img src="http://yannini.qiniudn.com/1100401F4650D5BA9B7E0907F4F41D1F0F38AD-C5D2-D4A8-0C84-6AB9C73F92FE.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;3、The Piano Guys 组合用大提琴和钢琴惊艳翻唱酷玩冠单 Paradise
&lt;img src="http://yannini.qiniudn.com/1100641F464F0BDEF7A57900E68D47A6F9F6D9-8C30-3047-4CA4-662DA0770807.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;网站涉及技术：
    Ruby on Rails
    Bootstrap
    Mysql
    Nginx&lt;/p&gt;

&lt;p&gt;特别感谢：
    七牛云存储
    coding.net
    百度云加速&lt;/p&gt;

&lt;p&gt;Ruby 圈内，有对该网站感兴趣的小伙伴，不论是技术，还是视频资料采集。都可以可以联系我。现在需要一个靠谱的合伙人。
Email: wanghao293@126.com&lt;/p&gt;

&lt;p&gt;你可以负责技术。
你也可以负责搞笑。
嘿嘿，2015 年大家一起加油吧！！&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Sat, 24 Jan 2015 12:32:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/23921</link>
      <guid>https://ruby-china.org/topics/23921</guid>
    </item>
    <item>
      <title>爬虫获取 ruby-china 职位地区分布数量统计</title>
      <description>&lt;p&gt;Jobs 数量地区分布图&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;#   +------+-----------+
#   | area | Job数量   |
#   +------+-----------+
#   |    1 |       424 |  北京
#   |    2 |       291 |  上海
#   |    3 |        73 |  广州
#   |    4 |        46 |  深圳
#   |    5 |        62 |  杭州
#   |    6 |        45 |  成都
#   |    7 |        39 |  remote
#   |    8 |       127 |  others
#   +------+-----------+

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;点赞最多的 Topic&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org//topics/13680" rel="nofollow" target="_blank"&gt;https://ruby-china.org//topics/13680&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;给薄荷网赞一个！&lt;/p&gt;

&lt;p&gt;下面是主要程序片段&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"获取ruby-china.org上的工作"&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:get_jobs&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:environment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;time_start&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;
  &lt;span class="no"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;74&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://ruby-china.org/jobs?page=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"//div[@class='topics']/div"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;topic_class&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;right_info_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"//div[@class='&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;topic_class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;']/div[@class='right-info']"&lt;/span&gt;
      &lt;span class="n"&gt;topic_path&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;right_info_path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;"/div[@class='pull-right replies']/a"&lt;/span&gt;
      &lt;span class="c1"&gt;# 获取点赞数量&lt;/span&gt;
      &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;
      &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;

      &lt;span class="c1"&gt;# 获取标题&lt;/span&gt;
      &lt;span class="n"&gt;title_path&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;right_info_path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/div[@class='infos']/div[@class='title']/a"&lt;/span&gt;
      &lt;span class="n"&gt;title&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title_path&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="c1"&gt;# 获取url&lt;/span&gt;
      &lt;span class="n"&gt;url_suffix&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title_path&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'href'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;url&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://ruby-china.org/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;url_suffix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="n"&gt;area&lt;/span&gt;            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cal_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;job&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;area: &lt;/span&gt;&lt;span class="n"&gt;area&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;up: &lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;time_end&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"rake 执行完毕！耗时&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt; &lt;span class="n"&gt;time_end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;time_start&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;秒"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Top 20 &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; select title, up, url from jobs order by up desc limit 20\G;
*************************** 1. row ***************************
title: [上海]薄荷科技寻找靠谱的 Rubyist
   up: 125
  url: https://ruby-china.org//topics/13680
*************************** 2. row ***************************
title: [广州] 招聘 Ruby 程序员【已结束】
   up: 124
  url: https://ruby-china.org//topics/14975
*************************** 3. row ***************************
title: [西安] 途途科技招聘 Ruby/Rails 工程师 / 实习生
   up: 111
  url: https://ruby-china.org//topics/18818
*************************** 4. row ***************************
title: [北京] 酷传招聘Ruby on Rails全职实习生/初级工程师，当然我们也喜欢高手
   up: 106
  url: https://ruby-china.org//topics/5112
*************************** 5. row ***************************
title: [上海][浦东][扩招]一名 Ruby 工程师（附靓照）【已结束】
   up: 102
  url: https://ruby-china.org//topics/12391
*************************** 6. row ***************************
title: [北京] 天际网寻觅初、中、高级 Rubyist [暂停招聘]
   up: 95
  url: https://ruby-china.org//topics/5745
*************************** 7. row ***************************
title: [南京]暴走漫画招聘 rails 程序员(内有无节操图，慎入)
   up: 94
  url: https://ruby-china.org//topics/12431
*************************** 8. row ***************************
title: [日本] 宣传下我现在就职的公司：日本COOKPAD
   up: 90
  url: https://ruby-china.org//topics/864
*************************** 9. row ***************************
title: [深圳] Knewone.com 招聘 Ruby/Javascript/iOS 程序员
   up: 90
  url: https://ruby-china.org//topics/11561
*************************** 10. row ***************************
title: [北京][上海][远程] Doorder 招聘 Ruby on Rails 高级开发工程师
   up: 89
  url: https://ruby-china.org//topics/19290
*************************** 11. row ***************************
title: [上海] 百度诚招高级研发工程师 Ruby
   up: 89
  url: https://ruby-china.org//topics/15393
*************************** 12. row ***************************
title: [北京] 招靠谱 Ruby 攻城狮
   up: 83
  url: https://ruby-china.org//topics/3867
*************************** 13. row ***************************
title: [上海] "英语流利说"诚聘 Rails 开发工程师
   up: 80
  url: https://ruby-china.org//topics/12746
*************************** 14. row ***************************
title: 此贴复活！[杭州] 急招 Ruby 工程师，前端工程师，iOS，安卓，产品经理，月薪 10k-25k,办公地点可以自选.
   up: 77
  url: https://ruby-china.org//topics/15650
*************************** 15. row ***************************
title: [已结束][上海] 掌誉网络科技招聘靠谱Ruby程序员 - 你看了以后可能几天都睡不好觉的招聘帖
   up: 76
  url: https://ruby-china.org//topics/8893
*************************** 16. row ***************************
title: [深圳] KnewOne 招聘开发实习生（北京也招聘前后端开发）
   up: 75
  url: https://ruby-china.org//topics/17881
*************************** 17. row ***************************
title: [欧洲] Chinese speaker Ruby/JS/Web Developer - 招聘已结束
   up: 75
  url: https://ruby-china.org//topics/12750
*************************** 18. row ***************************
title: [杭州] The Plant 招人
   up: 71
  url: https://ruby-china.org//topics/2391
*************************** 19. row ***************************
title: [杭州滨江] 急招 Ruby 大神？高手？长者？
   up: 68
  url: https://ruby-china.org//topics/17351
*************************** 20. row ***************************
title: [广州] 招聘 Ruby / Rails 程序员
   up: 67
  url: https://ruby-china.org//topics/4337
20 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;附加：PM2.5 对比 &lt;/p&gt;

&lt;p&gt;北京 vs 上海&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/beijing_vs_shanghai" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;北京 vs 广州&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/beijing_vs_guangzhou" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;北京 vs 杭州&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/beijing_vs_hangzhou" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;北京 vs 深圳&lt;/p&gt;

&lt;p&gt;&lt;img src="http://yannini.qiniudn.com/beijing_vs_shenzhen" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;个人爱好，不喜勿喷。&lt;/p&gt;</description>
      <author>ibugs</author>
      <pubDate>Tue, 04 Nov 2014 00:43:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/22449</link>
      <guid>https://ruby-china.org/topics/22449</guid>
    </item>
  </channel>
</rss>
