应用程序开发人员犯的数据库开发错误

Database development mistakes made by application developers

应用程序开发人员常见的数据库开发错误是什么?


1。未使用适当的索引好的。

这是一个相对容易,但它仍然会一直发生。外键上应该有索引。如果在WHERE中使用字段,则(可能)应该有一个索引。这样的索引通常应该根据需要执行的查询覆盖多个列。好的。

2。不强制引用完整性好的。

您的数据库可能在这里有所不同,但是如果您的数据库支持引用完整性——也就是说,所有外键都保证指向一个存在的实体——那么您应该使用它。好的。

在MySQL数据库中看到这种失败是很常见的。我不相信Myisam支持。依诺德确实如此。你会发现有人在使用myisam或者那些使用innodb但无论如何都不使用它的人。好的。

这里更多:好的。

  • 如果我总是用PHP控制数据库输入,那么约束(如非空和外键)有多重要?
  • 在数据库设计中是否确实需要外键?
  • 在数据库设计中是否确实需要外键?

三。使用自然而不是替代(技术)主键好的。

自然键是基于(表面上)唯一的外部有意义的数据的键。常见的例子有产品代码、两个字母的州代码(US)、社会保险号等。代理键或技术主键是那些在系统之外绝对没有意义的键。它们是专门为标识实体而发明的,通常是自动递增的字段(SQL Server、MySQL等)或序列(尤其是Oracle)。好的。

在我看来,你应该总是使用代理键。这个问题出现在以下几个问题中:好的。

  • 你喜欢你的主键吗?
  • 表中主键的最佳实践是什么?
  • 在这种情况下,您将使用哪种格式的主键。
  • 代理与自然/商业密钥
  • 我应该有一个专门的主键字段吗?

这是一个有争议的话题,在这个问题上你不能得到普遍的认同。虽然你可能会发现一些人,他们认为自然钥匙在某些情况下是可以的,但你不会发现对替代钥匙的任何批评,除了被认为是不必要的。如果你问我的话,这是一个很小的缺点。好的。

记住,即使是国家也可能停止存在(例如南斯拉夫)。好的。

4。编写要求DISTINCT工作的查询好的。

您经常在ORM生成的查询中看到这一点。查看Hibernate的日志输出,您将看到所有查询都以以下开头:好的。

1
SELECT DISTINCT ...

这是确保不返回重复行从而获得重复对象的一个捷径。你有时也会看到人们这样做。如果你看得太多,那就是一个真正的红旗。并不是说EDOCX1[1]不好或者没有有效的应用程序。它(在这两方面)都可以,但它不是用于编写正确查询的替代项或权宜之计。好的。

从我讨厌与众不同的原因来看:好的。

Where things start to go sour in my
opinion is when a developer is
building substantial query, joining
tables together, and all of a sudden
he realizes that it looks like he is
getting duplicate (or even more) rows
and his immediate response...his
"solution" to this"problem" is to
throw on the DISTINCT keyword and POOF
all his troubles go away.

Ok.

5。将聚合优先于联接好的。

数据库应用程序开发人员的另一个常见错误是没有意识到与联接相比,聚合(即GROUP BY子句)的成本要高出多少。好的。

为了让你了解这个话题有多广泛,我已经在这里写了好几次,并被否决了很多。例如:好的。

从SQL语句-"join"vs"group by and having":好的。

First query:

Ok.

1
2
3
4
5
SELECT userid
FROM userrole
WHERE roleid IN (1, 2, 3)
GROUP by userid
HAVING COUNT(1) = 3

Query time: 0.312 s

Ok.

Second query:

Ok.

1
2
3
4
5
SELECT t1.userid
FROM userrole t1
JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2
JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3
AND t1.roleid = 1

Query time: 0.016 s

Ok.

That's right. The join version I
proposed is twenty times faster than
the aggregate version.

Ok.

6。不通过视图简化复杂查询好的。

并非所有的数据库供应商都支持视图,但是对于那些支持视图的供应商,如果使用得当,他们可以大大简化查询。例如,在一个项目中,我使用了CRM的通用参与方模型。这是一种非常强大和灵活的建模技术,但可以导致许多连接。在这个模型中有:好的。

  • 党:人民和组织;
  • 当事人角色:当事人所做的事情,例如雇员和雇主;
  • 角色关系:这些角色如何相互关联。

例子:好的。

  • 特德是一个人,是党的一个亚型;
  • 泰德有许多角色,其中一个是员工;
  • 英特尔是一个组织,是政党的一个子类型;
  • 英特尔有许多角色,其中一个是雇主;
  • 英特尔雇佣了泰德,这意味着他们各自的角色之间存在着某种关系。

所以有五张桌子连接着泰德和他的雇主。假设所有员工都是个人(而不是组织),并提供此帮助者视图:好的。

1
2
3
4
5
6
7
8
CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id

突然间,您得到了一个非常简单的视图,您想要的数据是在一个高度灵活的数据模型上的。好的。

7。不清理输入好的。

这是一个巨大的。现在我喜欢PHP,但是如果你不知道自己在做什么,那么很容易创建易受攻击的站点。没有什么比小鲍比桌子的故事更能概括它了。好的。

用户通过URL、表单数据和cookie提供的数据应始终被视为恶意数据和净化数据。确保你得到了你所期望的。好的。

8。不使用准备好的语句好的。

准备好的语句是在编译一个查询时减去insert、updates和WHERE子句中使用的数据,然后在后面提供这些数据。例如:好的。

1
SELECT * FROM users WHERE username = 'bob'

VS好的。

1
SELECT * FROM users WHERE username = ?

或好的。

1
SELECT * FROM users WHERE username = :username

取决于你的平台。好的。

我见过这样做会让数据库陷入困境。基本上,任何现代数据库每次遇到新的查询时,都必须编译它。如果它遇到了以前看到的查询,那么您就给了数据库缓存已编译查询和执行计划的机会。通过进行大量的查询,您可以让数据库有机会了解并相应地进行优化(例如,通过将已编译的查询固定在内存中)。好的。

使用准备好的语句还可以为您提供关于某些查询使用频率的有意义的统计信息。好的。

准备好的语句还可以更好地保护您免受SQL注入攻击。好的。

9。规格化不够好的。

数据库规范化基本上是优化数据库设计或如何将数据组织到表中的过程。好的。

就在本周,我遇到了一些代码,其中有人将一个数组内爆,并将其插入数据库中的一个字段中。规范化,将该数组的元素视为子表中的单独行(即一对多关系)。好的。

这也是存储用户ID列表的最佳方法:好的。

I've seen in other systems that the list is stored in a serialized PHP array.

Ok.

但缺乏规范化有很多形式。好的。

更多:好的。

  • 正常化:多远就足够了?
  • SQL按设计:为什么需要数据库规范化

10。正常化太多好的。

这似乎与前面的观点相矛盾,但与许多事情一样,规范化是一种工具。它是一种达到目的的手段,而不是它本身的目的。我认为许多开发人员忘记了这一点,开始将"means"视为"end"。单元测试就是一个主要的例子。好的。

我曾经在一个系统上工作过,该系统为客户提供了一个庞大的层次结构,类似于:好的。

1
Licensee ->  Dealer Group -> Company -> Practice -> ...

这样,在获得任何有意义的数据之前,您必须将大约11个表连接在一起。这是一个很好的标准化的例子。好的。

更重要的是,仔细考虑的非规范化可能具有巨大的性能优势,但在执行此操作时必须非常小心。好的。

更多:好的。

  • 为什么过多的数据库规范化可能是一件坏事
  • 在数据库设计中进行规范化有多远?
  • 何时不规范化SQL数据库
  • 也许正常化不正常
  • 所有数据库规范化之母关于编写恐怖代码的辩论

11。使用专用弧好的。

排他弧是一种常见的错误,即表是用两个或多个外键创建的,其中一个且只有一个外键可以为非空。大错误。首先,维护数据完整性变得更加困难。毕竟,即使具有引用完整性,也没有任何东西可以阻止设置这些外键中的两个或多个(尽管有复杂的检查约束)。好的。

从实用的关系数据库设计指南:好的。

We have strongly advised against exclusive arc construction wherever
possible, for the good reason that they can be awkward to write code
and pose more maintenance difficulties.

Ok.

12。根本没有对查询进行性能分析好的。

实用主义占主导地位,特别是在数据库领域。如果你坚持原则,以至于它们变成了教条,那么你很可能犯了错误。以上面的聚合查询为例。聚合版本可能看起来"不错",但它的性能很糟糕。一个绩效比较本应该结束辩论(但事实并非如此),但更关键的是:首先发表这种不明智的观点是无知的,甚至是危险的。好的。

13。过度依赖工会,尤其是工会组织好的。

SQL术语中的联合仅连接一致的数据集,这意味着它们具有相同的类型和列数。它们之间的区别在于union all是一个简单的串联,在可能的情况下应首选union,而union将隐式地执行distinct以删除重复的元组。好的。

工会,就像独特的,有自己的位置。有有效的应用程序。但是如果你发现自己做了很多,特别是在子查询中,那么你可能做了一些错误的事情。这可能是查询构造不佳或数据模型设计不当的情况,迫使您执行这些操作。好的。

联合,尤其是在联接或从属子查询中使用时,会损坏数据库。尽可能的避免它们。好的。

14。查询中的使用或条件好的。

这可能看起来无害。毕竟,和是可以的。或者应该是很好吧?错了。基本上,"与"条件限制数据集,而"或"条件对其进行增长,但不会以优化自身的方式进行增长。尤其是当不同的或条件可能交叉时,这会迫使优化器有效地对结果执行不同的操作。好的。

坏的:好的。

1
... WHERE a = 2 OR a = 5 OR a = 11

更好的:好的。

1
... WHERE a IN (2, 5, 11)

现在,SQL优化器可以有效地将第一个查询转换为第二个查询。但可能不会。别这么做。好的。

15。没有设计他们的数据模型来提供高性能的解决方案好的。

这是一个难以量化的问题。它通常是通过它的作用来观察的。如果您发现自己为相对简单的任务编写粗糙的查询,或者为了找到相对简单的信息而进行的查询效率低下,那么您可能有一个糟糕的数据模型。好的。

在某些方面,这一点总结了前面的所有内容,但它更像是一个警告性的故事,即在需要第二次进行查询优化时,通常首先进行查询优化。首先,最重要的是,在试图优化性能之前,您应该确保有一个良好的数据模型。正如Knuth所说:好的。

Premature optimization is the root of all evil

Ok.

16。数据库事务的错误使用好的。

特定进程的所有数据更改都应该是原子的。也就是说,如果操作成功,它会完全成功。如果失败,数据将保持不变。-不应存在"半成品"变更的可能性。好的。

理想情况下,实现这一点的最简单方法是,整个系统设计应该通过单个insert/update/delete语句努力支持所有数据更改。在这种情况下,不需要特殊的事务处理,因为数据库引擎应该自动这样做。好的。

但是,如果任何进程确实需要作为一个单元执行多个语句以保持数据处于一致状态,则需要适当的事务控制。好的。

  • 在第一条语句之前开始事务。
  • 在最后一条语句之后提交事务。
  • 出现任何错误时,回滚事务。非常的NB!不要忘记跳过/中止错误之后的所有语句。

还建议您仔细注意数据库连接层和数据库引擎在这方面如何交互的子部分。好的。

17。不理解"基于集合"的范式好的。

SQL语言遵循适合特定类型问题的特定范式。不同的供应商特定的扩展,尽管语言斗争,以解决问题,在微不足道的语言,如Java,C语言,德尔菲等。好的。

这种缺乏理解的表现在一些方面。好的。

  • 不适当地在数据库上强加过多的程序逻辑或命令逻辑。
  • 不适当或过度使用光标。尤其是当一个查询就足够的时候。
  • 错误地假设触发器在多行更新中每行触发一次。

明确责任分工,努力用适当的工具解决每一个问题。好的。好啊。


开发人员的关键数据库设计和编程错误

  • 自私的数据库设计和使用。开发人员通常将数据库视为其个人持久对象存储,而不考虑数据中其他涉众的需求。这也适用于应用程序架构师。糟糕的数据库设计和数据完整性使第三方很难处理数据,并可能大幅增加系统的生命周期成本。报告和MIS在应用程序设计上往往是个差劲的表亲,只是事后才做的。

  • 滥用非规范化数据。过度处理非规范化的数据并尝试在应用程序中维护它是导致数据完整性问题的一个秘诀。谨慎使用非规范化。不希望向查询添加联接并不是取消规范化的借口。

  • 害怕写SQL。SQL并不是一门火箭科学,实际上它非常擅长完成它的工作。O/R映射层非常擅长执行95%的查询,这些查询很简单并且很适合该模型。有时SQL是完成这项工作的最佳方法。

  • 教条式的"无存储过程"策略。不管您是否相信存储过程是邪恶的,这种教条主义的态度在软件项目中是没有位置的。

  • 不了解数据库设计。正常化是你的朋友,而不是火箭科学。连接和基数是相当简单的概念——如果您参与了数据库应用程序开发,就没有理由不理解它们。


  • 不在数据库架构上使用版本控制
  • 直接针对实时数据库工作
  • 不阅读和理解更高级的数据库概念(索引、聚集索引、约束、物化视图等)
  • 无法测试可伸缩性…只有3行或4行的测试数据永远不会给您真实的实况性能。

  • 过度使用和/或依赖于存储过程。

    一些应用程序开发人员将存储过程视为中间层/前端代码的直接扩展。这似乎是Microsoft堆栈开发人员的一个共同特点(我是其中之一,但我已经摆脱了它),并生成了许多执行复杂业务逻辑和工作流处理的存储过程。在其他地方做得更好。

    如果事实证明某些真正的技术因素需要使用存储过程(例如,性能和安全性),则存储过程非常有用,例如,使大型数据集的聚合/筛选"接近数据"。

    我最近不得不帮助维护和增强一个大型的Delphi桌面应用程序,其中70%的业务逻辑和规则是在1400个SQL Server存储过程中实现的(其余部分是在UI事件处理程序中实现的)。这是一场噩梦,主要是由于在TSQL中引入有效的单元测试很困难,缺乏封装和糟糕的工具(调试器、编辑器)。

    在过去,我与Java团队合作,很快发现,在那个环境中,通常完全相反。一位Java架构师曾经告诉我:"数据库是为了数据,而不是代码。"

    现在我认为完全不考虑存储过程是错误的,但是在它们提供有用好处的情况下(参见其他答案),应该谨慎地使用它们(不是默认情况下)。


    第一个问题?他们只在玩具数据库上测试。所以,他们不知道当数据库变大时,他们的SQL会爬行,必须有人来稍后修复(你能听到的声音是我的牙齿磨牙)。


    不使用索引。


    相关子查询导致的性能不佳

    大多数时候,您希望避免相关的子查询。如果在子查询中存在对外部查询中某列的引用,则子查询是相关的。发生这种情况时,对于返回的每一行,子查询至少执行一次,如果在应用包含相关子查询的条件之后应用其他条件,则可以执行更多次。

    请原谅这个人为的例子和Oracle语法,但假设您希望找到自上次商店一天的销售额低于10000美元以来在您的任何一家商店雇用的所有员工。

    1
    2
    3
    4
    5
    6
    7
    select e.first_name, e.last_name
    from employee e
    where e.start_date >
            (select max(ds.transaction_date)
             from daily_sales ds
             where ds.store_id = e.store_id and
                   ds.total < 10000)

    本例中的子查询通过存储区标识与外部查询相关联,并将为系统中的每个员工执行。可以优化此查询的一种方法是将子查询移动到内联视图。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    select e.first_name, e.last_name
    from employee e,
         (select ds.store_id,
                 max(s.transaction_date) transaction_date
          from daily_sales ds
          where ds.total < 10000
          group by s.store_id) dsx
    where e.store_id = dsx.store_id and
          e.start_date > dsx.transaction_date

    在本例中,FROM子句中的查询现在是一个内联视图(也是一些特定于Oracle的语法),并且只执行一次。根据您的数据模型,此查询可能执行得更快。随着员工人数的增长,它的性能将优于第一个查询。如果只有很少的员工和多个商店(可能很多商店没有员工),并且每天的销售表都在商店ID上建立了索引,那么第一个查询实际上可以更好地执行。这不是一个可能的场景,但显示了相关查询可能比其他查询执行得更好。

    我见过很多次初级开发人员关联子查询,它通常对性能有严重影响。但是,在删除相关子查询时,请确保在删除前后查看解释计划,以确保不会使性能变差。


    根据我的经验:
    不与经验丰富的DBA通信。


    使用Access而不是"真实"数据库。有很多小型甚至免费的数据库,如SQL Express、MySQL和SQLite,它们可以更好地工作和扩展。应用程序通常需要以意想不到的方式扩展。


    忘记在表格之间建立关系。我记得当我刚开始在我现在的雇主工作的时候,我必须清理这个地方。


    我想补充一下:喜欢"优雅"的代码而不是高性能的代码。对数据库最有效的代码在应用程序开发人员眼中通常是丑陋的。

    相信过早优化的胡说八道。数据库必须在原始设计和任何后续开发中考虑性能。在我看来,性能是数据库设计的50%(40%是数据完整性,最后10%是安全性)。一旦将实际用户和实际流量放在数据库上,那些不是自下而上构建来执行的数据库将无法正常运行。过早的优化并不意味着没有优化!这并不意味着您应该编写几乎总是性能不好的代码,因为您发现这样做更容易(例如,除非所有其他操作都失败,否则在生产数据库中不应该允许使用游标)。这意味着你不需要考虑挤出最后一点性能,直到你需要。很多人都知道什么在数据库上性能更好,在设计和开发中忽略这一点充其量是短视的。


    使用Excel存储(大量)数据。

    我见过公司持有数千行并使用多个工作表(由于Excel以前版本的行限制为65535)。

    Excel非常适合于报表、数据表示和其他任务,但不应被视为数据库。


    不使用参数化查询。它们在停止SQL注入方面非常方便。

    这是一个不清理输入数据的特定示例,在另一个答案中提到。


    对于基于SQL的数据库:

  • 没有利用聚集索引或者选择了错误的列进行聚集。
  • 不使用串行(自动编号)数据类型作为主键来联接父/子表关系中的外键(int)。
  • 当插入或删除了许多记录时,不更新表的统计信息。
  • 当插入或删除了许多行时,不重新组织(即卸载、删除、重新创建、加载和重新索引)表(某些引擎在带有删除标志的表中实际保留删除的行)。
  • 不利用表达式上的片段(如果支持的话)处理事务率高的大表。
  • 为列选择错误的数据类型!
  • 没有选择正确的列名。
  • 不在表末尾添加新列。
  • 没有创建适当的索引来支持经常使用的查询。
  • 在可能值很少的列上创建索引,并创建不必要的索引。…还有更多要添加的。

  • 我讨厌开发人员使用嵌套的select语句,甚至函数返回查询"select"部分中select语句的结果。

    我真的很惊讶我在其他地方没有看到这个,也许我忽略了它,尽管@adam也指出了类似的问题。

    例子:

    1
    2
    3
    4
    5
    SELECT
        (SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
        ,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
    FROM
        MyTable c

    在这种情况下,如果myTable返回10000行,那么结果就像查询刚运行了20001个查询一样,因为它必须为每一行结果运行初始查询加上查询其他每个表一次。

    开发人员可以在只返回几行数据的开发环境中工作,而子表通常只有少量数据,但是在生产环境中,随着向表中添加更多数据,这种查询可能会以指数形式增加成本。

    一个更好(不一定完美)的例子是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT
         s.SomeValue As FirstVal
        ,o.OtherValue As SecondVal
    FROM
        MyTable c
        LEFT JOIN (
            SELECT SomeDate, MAX(SomeValue) as SomeValue
            FROM SomeTable
            GROUP BY SomeDate
         ) s ON c.Date = s.SomeDate
        LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria

    这使得数据库优化器可以将数据混合在一起,而不是对主表中的每个记录进行重新查询。我通常会发现,当我必须修复创建此问题的代码时,我通常会将查询速度提高100%或更多,同时降低CPU和内存使用率。


    • 在修复生产数据库中的某些问题之前不进行备份。

    • 对存储过程中的存储对象(如表、视图)使用DDL命令。

    • 害怕使用存储过程,或者害怕在ORM查询更有效/更适合使用的地方使用ORM查询。

    • 忽略使用数据库探查器,它可以准确地告诉您ORM查询最终转换为什么,从而在不使用ORM时验证逻辑,甚至用于调试。


    没有执行正确的标准化级别。您需要确保数据不重复,并且根据需要将数据拆分为不同的数据。您还需要确保没有过度遵循规范化,因为这会损害性能。


    • 因为"太神奇了"或者"我的数据库里没有"这样的原因,把冬眠这样的虫虫赶走了。
    • 过于依赖像冬眠这样的虫虫,试图把它推到不合适的地方。

    1-不必要地对WHERE子句中的值使用函数,但该索引的结果未被使用。

    例子:

    1
    where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate

    而不是

    1
    where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1

    在较小程度上:不向那些需要它们的值添加函数索引…

    2-不添加检查约束以确保数据的有效性。约束可以由查询优化器使用,它们确实有助于确保您可以信任不变量。没有理由不使用它们。

    3-在纯惰性或时间压力的情况下,向表中添加未规范化的列。事情通常不是这样设计的,而是演变成这样的。最终的结果是,当您在未来的发展中被丢失的数据完整性咬到时,您将要做大量的工作来清理混乱。

    想想看,一个没有数据的表重新设计是非常便宜的。一张有数百万条记录但不完整的桌子…重新设计并不便宜。因此,在创建列或表时进行正确的设计将在SPADES中进行分摊。

    4-数据库本身不怎么重要,但确实很烦人。不关心SQL的代码质量。事实上,您的SQL是用文本表示的,这并不意味着可以将逻辑隐藏在成堆的字符串操作算法中。完全有可能以一种您的程序员同事实际上可以阅读的方式来编写文本中的SQL。


    将数据库视为存储机制(即美化的集合库),因此从属于其应用程序(忽略共享数据的其他应用程序)


    前面已经说过了,但是:索引,索引,索引。我看到过很多企业Web应用程序性能不佳的情况,这些情况都是通过简单地进行一点分析(查看哪些表受到了很大的攻击),然后在这些表上添加一个索引来解决的。这甚至不需要太多的SQL编写知识,而且回报是巨大的。

    避免像瘟疫一样的重复数据。有些人主张一点点的重复不会伤害,而且会提高性能。嘿,我不是说你必须把你的模式折磨成第三种正常形式,直到它如此抽象以至于连DBA都不知道发生了什么。只要明白,只要你复制一组名字,或邮政编码,或运输编码,副本最终会失去同步。会发生的。然后在运行每周维护脚本的过程中,你会被踢到自己身上。

    最后:使用清晰、一致、直观的命名约定。以同样的方式,一段编写良好的代码应该是可读的,一个好的SQL模式或查询应该是可读的,并且实际上告诉您它在做什么,即使没有注释。六个月后,当你需要在桌子上保养的时候,你会感谢你自己的。与"从ntnlaccts中选择accntnbr,billdat"相比,"SELECT account_number, billing_date FROM national_accounts"更易于使用。


    在运行删除查询(特别是在生产数据库上)之前不执行相应的选择查询!


    二十年来我见过的最常见的错误:没有提前计划。许多开发人员将创建一个数据库和表,然后在构建应用程序时不断修改和扩展表。最终结果往往是一团糟,效率低下,很难清理或简化以后。


    对管理应用程序中的数据库连接没有足够的关注。然后你会发现应用程序、计算机、服务器和网络都被阻塞了。


    a)将查询值硬编码为字符串b)将数据库查询代码放入Windows窗体应用程序的"onButtonPress"操作中

    我都看过。


  • 认为他们是DBA和数据建模者/设计师,而在这些领域没有任何形式的正式灌输。

  • 认为他们的项目不需要DBA,因为这些东西都是简单/琐碎的。

  • 未能正确区分应在数据库中完成的工作和应在应用程序中完成的工作。

  • 未验证备份或未备份。

  • 在代码中嵌入原始SQL。


  • 使用ORM进行批量更新
  • 选择超出需要的数据。同样,通常在使用ORM时完成
  • 在循环中触发SQLS。
  • 没有良好的测试数据,只在实时数据上注意到性能下降。

  • 不了解数据库并发模型以及这如何影响开发。事后添加索引和调整查询很容易。但是,在设计应用程序时没有考虑热点、资源争用正确的操作(假设您刚刚读到的内容仍然有效!)可能需要在数据库和应用程序层中进行重大更改,以便稍后更正。


    这里有一个视频链接,叫做"经典数据库开发错误和五种克服错误的方法",作者Scott Walz。


    不了解DBMS在引擎盖下的工作方式。

    如果不了解离合器的工作原理,就不能正确地驾驶斗杆。如果你不知道你只是在写硬盘上的文件,你就无法理解如何使用数据库。

    明确地:

  • 你知道什么是聚集索引吗?你在设计你的模式时考虑过吗?

  • 你知道如何正确使用索引吗?如何重用索引?你知道什么是覆盖指数吗?

  • 很好,你有索引。索引中的1行有多大?当你有大量的数据时,索引会有多大?那能很容易地融入记忆吗?如果不能,它就不能作为一个索引。

  • 你在MySQL中使用过explain吗?伟大的。现在诚实地对自己说:你看到的一半都明白了吗?不,你可能没有。修好。

  • 您了解查询缓存吗?你知道什么使一个查询不可执行吗?

  • 你用的是Myisam吗?如果你需要全文搜索,那么Myisam的就太糟糕了。使用狮身人面像。然后切换到Inno。


  • 嗯,我不得不说,应用程序开发人员犯的最大错误是没有正确地规范化数据库。

    作为一名应用程序开发人员,我认识到正确的数据库结构、规范化和维护的重要性;我花了无数时间在数据库结构和管理方面进行教育。根据我的经验,每当我开始与一个不同的开发人员合作时,我通常必须重新构建整个数据库,并更新应用程序以适应,因为它通常是畸形的和有缺陷的。

    例如,我开始使用一个新项目,开发人员要求我在该站点上实现Facebook连接。我打开数据库,查看我必须处理的内容,发现任何给定用户的每一点信息都被塞进一个表中。我花了六个小时写了一个脚本,将表组织成四到五个单独的表,另外两个脚本让应用程序使用这些表。请规范化您的数据库!这会使其他的事情都不那么令人头痛。


    许多开发人员倾向于对数据库执行多个查询(通常查询一个或两个表),提取结果并在爪哇/c/c++中执行简单操作-所有这些操作都可以用单个SQL语句完成。

    许多开发人员通常不知道在开发环境中,数据库和应用服务器都在他们的笔记本电脑上,但在生产环境中,数据库和应用服务器将在不同的机器上。因此,对于每个查询,在应用服务器和数据库服务器之间传递的数据都有额外的N/W开销。我很惊讶地发现,从应用服务器到数据库服务器进行的数据库调用中有多少是为了向用户呈现一个页面而进行的!


    • 非常大的事务,插入/更新大量数据,然后重新加载。基本上,这是因为不考虑数据库工作的多用户环境。

    • 函数的过度使用,特别是在select和where子句中导致函数在结果中被一次又一次地调用。我认为,这符合一般情况,即他们试图以更习惯的过程方式工作,而不是充分利用SQL。


    我认为所有开发人员和DBA所犯的最大错误是对约定的信任太多。我的意思是,公约只是指导方针,在大多数情况下都会起作用,但不一定总是如此。我很好的例子是规范化和外键,我知道大多数人不喜欢这样,但是规范化也会导致复杂性和性能损失,所以如果没有理由将电话号码移动到电话表中,就不要这样做。在外键上,它们对大多数情况都是很好的,但是如果您试图创建一些在需要时可以自己使用的东西,那么在将来,外键将是一个问题,而且您的性能也会变差。不管怎样,正如我所说,规则和惯例是有指导意义的,它们应该始终是,但不一定要实现的,对每一个案例的分析总是应该做的。


    当在开发机器上运行得很快的查询在向应用程序抛出一些流量时爆炸并阻塞时,归咎于DB引擎。


    最大的错误是在代码更新或插入数据时有一个循环,当一个简单的基于集合的解决方案可以更快、更简单地完成这个技巧时。


    15-使用一些疯狂的构造和应用程序逻辑,而不是简单的合并。


    如果您使用的是复制(mysql),那么以下函数是不安全的,除非您使用的是基于行的复制。

    1
    USER(), CURRENT_USER() (or CURRENT_USER), UUID(), VERSION(), LOAD_FILE(), and RAND()

    请参阅:http://dev.mysql.com/doc/refman/5.1/en/replication-features-functions.html


    有一件事我可以补充,学习使用分析功能,如分区,排名,密集排名(对于Oracle)。它们对于复杂的查询是绝对必要的。

    其他的建议是,如果可能的话,在您的开发团队中有一个专门的数据库开发人员,他擅长SQL、数据库建模、调优等(尽管不是DBA)。这种技能是一项巨大的财富。


    1)如何正确理解Java和数据库之间的正确交互。

    2)过度解析、不正确或不重用SQL

    3)无法使用绑定变量

    4)当数据库中的SQL SET逻辑工作(更好)时,在Java中实现过程逻辑。

    5)在投入生产前未进行任何合理的性能或可扩展性测试

    6)使用Crystal Reports,但未能在报表中正确设置架构名称

    7)由于不了解执行计划,使用笛卡尔产品实现SQL(您是否看过解释计划?)