sql反模式分析2

第八章 多列属性
         目标:存储多值属性  为一个bug设置多个标签
         反模式:创建多个列,为bugs创建tag1,tag2,tag3几个列保存标签。标签必须放于其中一个。
                 1.查询数据,比如搜索这三列,可以使用in语句
                 2.添加和删除  update bugs set tag1=nullif(tag1,'perfor'),tag2=nullif(tag2,'perfor'),tag3=nullif(tag3,'perfor')这个能把值更新到其中为空的那一列,如果都不为空,则不作更新。            3.确保唯一性。无法确保三列的值不一样。
                4.处理不断增长的值集。三列可能不够用,如果在不断的增加列,性能开销将越来越大,而且sql查询更新将越来越复杂。
         解决方案:创建从属表  
         将具有同样意义的值存在同一列中。
   第九章:元数据分类  案例:为一个客户表增加每年的收入情况,每年的收入情况都存在单独的列中,导致每一年就需要新增一个列存储该年的收入。
           目标:支持可扩展性
           反模式: 克隆表与克隆列
                1.不断产生的新表 按照年份对bug表进行拆分,拆成bugs_2008,bugs_2009等多张表,然后按照需要需要修改对应的sql。
               2.管理数据完整性 如果有数据被误写到其他表中,则可能导致统计的一年的bugs数之类的数据不准确。没有任何办法自动对数据和相关表名做限制。但可以在每张表创建的时候使用check的约束。
               3.同步数据  如果发现某条记录原来是在2009这个表中,但时间弄错了,需要修改为2008的,这样订正数据就比较麻烦。需要好几条sql。
              4.确保唯一性。 如果需要做数据迁移,则需要保证记录的主键id值不会与目标表的主键记录冲突。而且对于那些只支持单表ID唯一的数据库产品,实现这样的功能还需要定义一张额外的表存储产品主键的值。
              5.跨表查询  如果需要查询所有的bugs数,则需要把每个表用union进行查询.
              6.同步元数据.如果值在某个表增加一列,其他表没有增加,则联合查询不用使用*,需要列出所有列名.
             7.管理引用完整性. 其他表就不能引用bugs的外键了,因为有多个bugs表.
             8.标识元数据分裂列 如果有其他表保护bugx_fiexd_2008,bugx_fixed_2009,则以后肯定需要增加bugx_fixed_2010.
          解决方案: 手工分割表的一个合理使用场景是归档数据。把没用的数据迁移到历史表中。
               1.使用水平分区。MYSQL5.1所支持的分区特性,在createtable时执行pritition by hash(year(date)reported)) partitions 4.
               2.使用垂直分区。根据列来对表进行拆分。将一些BLOB或者TEXT字段拆分到其他表存储。
               3.解决元数据分裂列。创建关联表。
          别让数据繁衍元数据。


   物理数据库设计反模式
       第10章:取整错误。
          目标:使用小数取代整数,运算结果必须准确。
          反模式:使用float类型
                  无限循环小数无法使用存储表示。
                  在SQL中使用FLOAT类型,放大查询结果差异比较大。无法使用比较操作,必须使用近似相等查询,但是阀值需要使用合适。
          解决方案:oracle的FLOAT类型表示的是精确值,而BINARY_FLOAT则是非精确值。
                   使用NUMERIC类型。SQL的NUMERIC或者DECIMAL类型来代替FLOAT存储小数。 NUMERIC(9,2) 精度,刻度 这样仍然无法存储无限精度的数据。
          尽可能不要使用浮点数。
     第11章:每日新花样  需要给称呼列加入约束指定这些候选值
          目标:限定列的有效值  希望数据库能够拒绝无效值的输入
          反模式:在列定义上指定可选值。很多数据库设计人员习惯在定义列的时候指定所有可选的有效数据。
                   create table bugs(status varchar(20) check(status in('new','in','fixed')).
                   mysql也支持用ENUM关键词来约束。但是mysql存储的是序数,而非字符串。
                  1.中间的是哪个  无法获得status列中值的枚举列表,如果使用distinct来查询bugs表,但是刚开始没数据,查询的结果为空。如果使用INFORMATION_SHEMA系统视图,则还需要解决解决格式。
                 2.添加新口味。添加或者删除一个候选值。没有什么语法支持从ENUM或者check约束中添加或者删除一个值。只能用一个新的集合重新定义这一列。一些数据库只有在表为空表是才能改变某一列的数据。那么就需要先将数据导出,改变之后再导入。
                 3.老的口味永不消失。旧的值无法删除。
                4.可一致性地下。check约束,域和UDT在各种数据库支持形式不同意。ENUM是mysql特有的特性。
        解决方案:在数据中指定值,通过创建一张检查表bug_status,定义status列中出现的候选值,然后定义一个外键约束。
                 1.查询候选值集合。直接查询检查表。
                 2.更新检查表中的数据。插入更新操作很方便。
                 3.支持废弃数据。可以通过在bug_status表增加一列来表示是否已经弃用。
                4.良好的可移植性。
        在验证固定集合的候选值时使用元数据。在验证可变集合的候选值时使用数据。
     第12章:幽灵文件  只保存数据库文件,没有保存数据库中保存的文件路径对应的数据库外的文件。
           目标:存储图片或其他多媒体大文件。
           反模式:假设必须使用文件系统,可以使用BLOB字段存储文件,或者只在数据库存储文件路径。
                  1.文件不支持DELETE  垃圾回收问题。如果图片在数据库之外,删除某条记录之后无法自动将对应文件删除。
                  2.文件不支持事务隔离。数据库事务在提交之前,所有改变对外都不可见。但是数据库之外的文件改变则立刻体现到外界。
                  3.文件不支持回滚操作。数据库可以回滚,但是文件系统无法回滚。
                 4.文件不支持数据库备份工具。
                 5.文件不支持SQL的访问权限设置。
                 6.文件不是SQL数据类型。无法验证文件路径是否正确。
          解决方案:在需要时使用BLOB类型。
                   MYSQL MEDIUMBLOB:16M oracle:LONGRAW 2GB
                   MYSQL有load_file()用来读取一个文件存储到BLOB列
          存储在数据库之外的数据不由数据库管理。
    第13章: 乱用索引
          目标:优化性能
          反模式:无规划的使用索引
                  1.无索引
                  2.索引过多  不需使用的索引无法获得任何好处,只有开销。
                  3.索引也无能为力 常犯的错误是进行一个无法使用索引的查询
          解决方案:所有不重复的值的记录和总计数条数之比越低,索引的效率就越低。
                 1.测量  ORACLE:TKProf mysql:慢查询日志
                 2.解释  查询执行计划
                 3.挑选   索引覆盖
                 4.测试 
                 5.优化  索引预载入:mysql使用 load index into cache语句。
                 6.重建:更新或者删除导致索引修改,需要定期对索引进行维护。mysql:analyze table or optimize table oracle:alter index rebuild
         了解你的数据,了解你的查询请求,然后MENTOR你的索引。
   
  查询反模式
     第14章:对未知的恐惧。
           目标:辨别悬空值 SQL支持一个特殊的空值,NULL。
              增加记录时使用NULL代替那些还不确定的值。
             一个给定的列如果没有合适的值,可以使用NULL代替。
             当传入参数无效时,一个函数的返回值也可以是NULL。
            在外联结查询中,NULL被用来当做未匹配的列的占位符。
         反模式:将NULL作为普通的值,反之亦然。
             1.在表达式中使用NULL。 如果某个字段为NULL,表达式结果也是NULL。
             2.搜索允许为空的列: select * from bugs where aggin_to=123 或者select * from bugs where not(assin_to=123)都不会返回这列为null的值。
                                  而且查询null或者非null是不能用where assin_to=NULL或者assin_to<>NULL。使用is null
             3.在查询参数中使用NULL 不能在查询参数assin_to=?传入NULL值
             4.避免上述问题:使用默认值来代替NULL,按时查询计算时仍然需要制定<>默认值
        解决方案:将NULL视为特殊值
               1.在标量表达式中使用NULL 表达式中一个值为NULL,则结果就为NULL。
               2.在布尔表达式中使用NULL。
              3.检索NULL值。SQL-99中额外定义了一个比较断言 IS DISTINCT FROM
              4.声明NOT NULL列。
             5.动态默认值。使用COALESCE()函数返回一个非NULL的参数。
         使用NULL来表示任意类型的悬空值。
   第15章:模棱两可的分组
       目标:获取每组的最大值
       反模式: 引用非分组列
               1.单值规则 一个分组只能返回单一的值 
               2.我想要的查询 如果分组后通过max获得的有两列的值是一样的,那么就无法返回哪条记录的其他列。不能使用max和min两个聚合函数定位到不同的记录。
       解决方案: 无歧义的使用列
               1.只查询功能依赖的列;
              2.使用关联子查询
              3.使用衍生表
              4.使用join 
              5.对额外的列使用聚合函数
             6.连接同组所有值 mysql使用GROUP_CONCAT()函数将这一组中所有的值连在一起。
        遵循单值规则,避免获得模棱两可的查询结果。
    第16章:随机选择  设计一个随机广告展示的查询
        目标:获得样坏死记录
       反模式:随机排序 select * from bugs order by rand() limit 1; 使用rand()简单,但是无法利用索引,因为没有索引会基于随机函数返回的值,导致一次全表排序。
       解决方案:没有具体的顺序。
                 1.从1到最大值之间随机选择  select b1.* from bugs as b1 join(select(ceil(rand() *(select max(bug_id) from bugs)) as rand_id) as b2 on(b1.bug_id=b2.bug_id);
                 2.选择下一个最大值。 select b1.* from bugs as b1 join(select(ceil(rand() *(select max(bug_id) from bugs)) as rand_id) as b2 where b1.bug_id>=b2.bug_id order by b1.bug_id limit 1;
                3.获得所有键值,随机选择一个。 程序选择一个,查询两次
                4.使用偏移量选择随机行。
                5.专有解决方案。SQL server 使用tablesample函数。 oracle使用sample函数。
        有些查询是无法优化的,换种方式试试看。
     第17章:可怜人的搜索引擎
         目标:全文检索
         反模式:模糊匹配断言 SQL提供了模式匹配断言来比较字符串,最常用的就是like语句。还有REGEXP正则表达式匹配。 不过缺点当然就是性能问题了。
         解决方案:使用正确的工具
                  1.数据库扩展 mysql能够对char,varchar,text定义一个全文索引,使用match进行全文查询.oracle使用context支持,然后通过contains()操作符搜索.sqlserver和postgreSQL也有对全文索引的支持.
                2.第三方搜索引擎:Sphinx search lucene
         你不必使用SQL来解决所有的问题.
      第18章:意大利苗条查询
          目标:减少sql查询数量
          反模式:使用一部操作解决复杂问题
                  1.副作用 查询多少bug已经修复,多少bug还打开。select p.product_id,count(f.bug_id) as count_fixed,count(o.bug_id) as count_open from bugsproduct p left outer join bugs f on(p.bug_id=f.bug_id and f.status='fixed') left outer join bugx o on(p.bug_id=o.bug_id and o.status='open') where p.product_id=1 group by p.product
                    这条sql查询出来count_fixed和count_open都是84,而实际上12个fixed,7个open,刚好84是12*7 这种查询是有问题。
         解决方案:分而治之
                 1.分两条sql来查询 。select p.product_id,count(f.bug_id) as count_fixe from bugsproduct p left outer join bugs f on(p.bug_id=f.bug_id and f.status='fixed') where p.product_id=1 group by p.product 。select p.product_id,count(o.bug_id) as count_open from bugsproduct p left outer join bugx o on(p.bug_id=o.bug_id and o.status='open') where p.product_id=1 group by p.product
                 2.寻找union标记  根据单个结果集再使用union all合并。
          尽管SQL支持用一行代码解决复杂的问题,但也别做不切实际的事情。
       第19章:隐式的列  联合查询如果两个表有列名一样的列,则会只取其中一个。
            目标:减少输入  可以使用*获取所有列
            反模式:捷径会让你迷失方向
                    1.破坏代码重构,比如增加一列之后,原来insert没有指定列名的则现在会报错,少一列的值了。 select也一样,如果删除一列后,应用代码获取列的可能也会出错。
                    2.隐藏的开销 获取一些没用的列,会增加网络开销和性能。
            解决方案:明确列出列名
           随便拿,但是拿了就必须吃掉。
     
    应用程序开发反模式
           第20章 明文密码
              目标:恢复和重置密码  现在一般都是使用邮箱让用户恢复和重置密码
              反模式:使用明文存储密码
                      1.存储密码 sql被劫持 
                      2.验证密码
                      3.在email中发送密码,email有可能被劫持
             解决方案:先哈希,后存储
                    mysql扩展支持SHA2()函数返回256位的哈希串
                    哈希暴力破解,可以先加密后再进行哈希。
                    在SQL中隐藏密码,在程序中生成哈希串之后,在sql中直接使用哈希串。
                   重置密码,而非恢复密码。
            如果密码对你可读,那么对于攻击者也是如此。
          第21章:SQL注入
              目标:编写SQL动态查询
              反模式:将未经验证的输入作为代码执行
              解决方案:不相信任何人
                    1.过滤输入内容。
                    2.参数化动态内容
                    3.给动态输入的值加引号
                    4.将用户与代码隔离
                   5.找个可靠的人来帮你审查代码
              让用户输入内容,但永远别让用户输入代码。
          第22章:伪键洁癖
                目标:整理数据
                反模式:填充角落
                     1.不按照顺序分配编号 
                    2.为现有行重新编号
                    3.制造数据差异 重新主键不是一个好习惯
               解决方案:1.定义行号。2.使用GUID 太长,随机的,需要16字节
               将伪键当做行的唯一性标识,但他们不是行号。
         第23章:非礼勿视
              目标:写更少的代码
              反模式:无米之炊 忽略数据库API的返回值,将程序代码跟SQL混在一起
                  1.没有诊断的诊断 在多条sql顺序执行过程中,最好对结果进行诊断,保证错误能够快速定位。
                  2.字里行间 花费大量时间调试生成sql字符串的代码
              解决方案:优雅的从错误中恢复
                 1.保持节奏 检查数据库API的返回状态和异常。
                 2.回溯你的脚步。sql语句记录,输出,调试。
          发现并解决代码中的问题已经很苦难了,就别再盲目的干了。
        第24章:外交豁免权
              目标:最佳实践 使用版本控制工具管理源代码,编写单元测试脚本;编写文档,代码注释。
              反模式:将SQL视为二等公民。

转载于:https://www.cnblogs.com/zhwj184/archive/2012/07/22/3119630.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

更多信息请关注微信公众号_为什么我们更多地关注表面异常?

更多信息请关注微信公众号Don’t you feel lucky to find a single seasoned curly fry in your bunch of plain old boring french fries? Do you remember highlighting important texts of your study materials before the exams? Both situations might seem irrelevant…

eclipse中的汉字极小的解决方案(转载)

eclipse中的汉字极小的解决方案(转载) 可能新装了eclipse后&#xff0c;写java代码的时候发现&#xff0c;写注释的时候发现&#xff0c;汉字小的可怜&#xff0c;网上搜一下&#xff0c;又是改字体又是设置字体大小&#xff0c;试用后发现都不是针对这个的方法。 无奈在自己摸…

面试官经常问的观察者模式如何实现~

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以 点此加我微信ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

旅行者 问题_门槛项目:没有旅行者回到他的原籍城市。

旅行者 问题Sohini Mukherjee| MFA| Spring 2020Sohini Mukherjee | 外交部| 2020年Spring Artivive app to see the full Artivive应用程序可查看完整的#AR experience.#AR体验。 Prompt:提示&#xff1a; As second semester, first year graduate students, you are at a …

产品经理懂技术=流氓会武术(zz)

最近七年&#xff0c;我都在做互联网产品&#xff0c;其中前五年分别在创业公司和上市公司里&#xff0c;做别人的产品&#xff1b;近两年在创业&#xff0c;做自己的产品。 我的体会是&#xff1a;产品经理需要懂技术&#xff0c;创业者尤其需要。但前提是你总觉得有股憋不住的…

技术人的七大必备特质

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以 点此加我微信ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

figma下载_在Figma中进行原型制作的技巧和窍门

figma下载自定义过渡和微交互 (Custom transitions and micro-interactions) Yep, I know that there are a lot of useful built-in transition effects in Figma already, but here I want to talk about custom micro-interactions, complicated transitions and show you h…

布局收藏用

http://www.aa25.cn/layout/index.shtml转载于:https://www.cnblogs.com/OceanChen/archive/2012/07/25/2608882.html

技术日新月异,发展迅速,如何不断扩展视野

技术日新月异&#xff0c;发展迅速&#xff0c;作为一个与时俱进的互联网人&#xff0c;需要不断地学习扩宽视野。今天为大家推荐几个技术领域中出类拔萃的公众号&#xff0c;它们的每一篇推文都值得你点开&#xff01;1叶小钗技术管理 技术转型 公司治理叶小钗&#xff0c;原腾…

不想当全栈的设计师不是_但我不想成为产品设计师

不想当全栈的设计师不是重点 (Top highlight)I’ve made a huge mistake, I thought to myself, as a realization washed over me in the middle of an interview for a product design role.我对自己想&#xff0c;我犯了一个巨大的错误&#xff0c;因为在接受产品设计职务的…

学习 WCF (6)--学习调用WCF服务的各种方法

来自&#xff1a;http://www.cnblogs.com/gaoweipeng/archive/2009/07/26/1528263.html 根据不同的情况&#xff0c;我们可以用不同的方法调用WCF服务&#xff0c;本文简单总结了一下调用WCF的一些方法(代理类&#xff0c;Ajax...)&#xff0c;分享给大家。开发工具调用WCF 这中…

[科普文] Vue3 到底更新了什么?

Vue3 已经发布一段时间了&#xff0c;这个版本从底层实现到上层 API 设计都发生了非常大的变化&#xff0c;但具体改变了些什么呢&#xff1f;一起简单盘点下&#xff1a;一、Composition API使用传统的option配置方法写组件的时候问题&#xff0c;随着业务复杂度越来越高&…

ipados_如何设计具有最新iPadOS 14功能的出色iPad应用

ipadosWe all know that iPad Pro already has a seriously powerful computing power and that it’s possible to create meaningful stuff with Apple Pen.我们都知道iPad Pro已经具有强大的计算能力&#xff0c;并且可以使用Apple Pen创建有意义的东西。 But do we really…

分组显示的ListView分页加载数据

参考&#xff1a; http://www.cnblogs.com/qianxudetianxia/archive/2011/06/07/2074326.html 分组的ListView的拖拽 http://www.cnblogs.com/qianxudetianxia/archive/2011/06/13/2079253.html ListView分页加载数据 http://blog.csdn.net/cjjky/article/details/6898871转载于…

67行JS代码实现队列取代数组,面试官刮目相看

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以 点此加我微信ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

ux和ui_我怎么知道UI / UX是否适合我?

ux和ui重点 (Top highlight)I’m super excited to be writing this as it’s the first official issue of Visual Q’s! If you don’t already know, this will be a monthly advice column for designers. If you join the newsletter, you’ll receive this before it goe…

HTML4和HTML5的区别[转]

HTML5是最新的HTML标准&#xff0c;或迟或早&#xff0c;所有的web程序员都会发现需要使用到这个最新的标准&#xff0c;而且&#xff0c;很多人都会感觉到&#xff0c;重新开发一个HTML5的网站&#xff0c;要比把一个网站从HTML4迁移到HTML5上容易的多&#xff0c;这是因为这两…

vs2017字体最佳选择_如何为下一个项目选择最佳字体? 一个简单的游戏

vs2017字体最佳选择“If I have the right font, half my design battle is already won!”“如果我使用正确的字体&#xff0c;那么我的设计大战已经赢了一半&#xff01;” In my first UX Design job, my AVP( Satish if you’re reading this, this one’s for you. ) onc…

浅谈初中级前端学习方法~

大家好&#xff0c;我是若川。 常有小伙伴问我如何学习前端开发。今天就简单谈下学习方法&#xff0c;方法可能主要适用于初中级前端。回想我们高中学习&#xff0c;是不是都是"以课本为主&#xff0c;其他资料为辅"。而且课堂上记笔记&#xff0c;然后通过大量练习&…

HDU-水饺基情 二维树状数组

该题就是简单的二维树状数组&#xff0c;保留一份棋盘的最新状态即可&#xff0c;树状数组里面就只保留在原有基础上增加或者减少的某一种饺子的数量。 代码如下&#xff1a; #include <cstring> #include <cstdlib> #include <cstdio> using namespace std;…