SQL 通配符真的很糟糕么

而那个ActiveRecord Query Interface,默认生成的SQL可是select *啊,开发的时候的确不碍事,但总不能就这样发布了,还得把所有用到的column名字都补回去,下次改到这里再注释掉。要不就不用ActiveRecord Query Interface。

现在,还有谁敢拿着里面还有select *的代码去发布啊,现在都找不到多少PHP代码里面到处都是select *了吧。

先说说优点:

一、打字少!看看下面对比,哪个简单就不用说了,更少的输入意味着更少的错误:

select * from bugs;

select bug_id, date_reported, summary, description, resolution, reported_by,assigned_to, verified_by, status, priority, hours,......, from bugs;

二、在添加和修改或删除的时候不需要更改查询语句。

上面这两点都满足了程序员“懒”的习惯。所以大家都非常喜欢使用。

下面谈谈缺点:

说到这里一定会有同学跳出说:这有性能问题,不能这么用! 的确,在在查询中使用通配符会影响性能,一次查询过多(有时候不需要的列也会被查到)会增加客户端和数据库之间的网络传输开销。

why AR's default SELECT * is not a big deal

一、性能问题永远不是应该最先考虑的问题。 很少应用的数据会达到百万、千万级别。在开发阶段代码简单灵活可扩展永远是第一位的。

二、考虑到两种特殊情况,一个表字段非常多或是有大字段(text/blob类型)。这种情况最彻底的解决方案是垂直拆分表和剥离大字段。

比如users这样的表很大,将users表分成accounts + user_blog_parts + user_ask_parts + user_topic_parts等。

带有大字段的表topics分成topics和topic_texts。

三、不使用通配符会带来更多的Query Cache Miss和额外的缓存存储开销.无论是数据库级别的Query Cache还是 ActiveRecord级别的Query Cache。原因很简单Query Cache使用sql语句作为缓存key,会把 select * 和 select colum1,column2 当作不同的查询。

mysql> select * from users order by id limit 1;

mysql> SHOW STATUS LIKE '%Qcache%';

+-------------------------+----------+

| Variable_name | Value |

+-------------------------+----------+

| Qcache_free_blocks | 1 |

| Qcache_free_memory | 16690672 |

| Qcache_hits | 3 |

| Qcache_inserts | 6 |

| Qcache_lowmem_prunes | 0 |

| Qcache_not_cached | 70 |

| Qcache_queries_in_cache | 6 |

| Qcache_total_blocks | 16 |

+-------------------------+----------+

8 rows in set (0.00 sec)

mysql> select id,nick_name,email from users order by id limit 1;

1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE '%Qcache%';

+-------------------------+----------+

| Variable_name | Value |

+-------------------------+----------+

| Qcache_free_blocks | 1 |

| Qcache_free_memory | 16689648 |

| Qcache_hits | 3 |

| Qcache_inserts | 7 |

| Qcache_lowmem_prunes | 0 |

| Qcache_not_cached | 70 |

| Qcache_queries_in_cache | 7 |

| Qcache_total_blocks | 18 |

+-------------------------+----------+

8 rows in set (0.00 sec)

mysql>

四、和Query Cache类似,如果项目用了类似CacheMoney这样的行缓存插件,通配符方式会带来额外的性能提升,有些查询甚至不需要去hit db,比指定列的方式省的那一点儿流量强的多。

五、有些查询使用select *不能进行覆盖索引优化。但是别忘了AR是可以使用select 选项的... 默认select * ,在特殊的地方手动指定查询列,这有什么问题呢?这就是CoC啊..

结论:

所以,单从一条查询来看某些做法可能是最好的,但是从整体的角度看未必是最优的。 有些同学干了很多脏活累活儿,看起来很勤劳勇敢的样子,但是也未必起到什么效果:-)

相关推荐