数据采样率优化

All lectures for ZH purposes
第 1 级 , 课程 879
可用

6.1 简介

现在让我们从理论转向实践。

“从理论上讲,理论和实践之间没有区别。实际上,他们是。”

我们生活在现实世界中,所有的软件产品最终都是为活着的人创造的。这些活着的人对加载缓慢的网站和运行缓慢的程序感到非常恼火。

而如果一个数据库查询花费的时间超过一秒,这是不可接受的。用户根本不会使用页面/功能如此缓慢的产品。

但通常,为了显示一个页面,您需要对数据库执行几十次查询。如果它们是按顺序执行的,那么您将不再有第二个限制,但假设每个请求 100 毫秒。

以下是程序员加速数据库查询的前 5 种方法:

  1. 为数据库中的表添加索引。
  2. 重写和优化查询。
  3. 在数据库端启用(和配置)缓存。
  4. 在客户端启用缓存。
  5. 执行数据库反规范化。

大多数情况下,您已经熟悉了所有这些内容,因此以下内容只是实用建议。

6.2 指数

众所周知,使用数据库占据了几乎所有站点的大部分工作。它正在处理最常成为 Web 应用程序瓶颈的数据库。

在本文中,我想提供有关使用 MySQL 的实用建议。

我马上说:

  • 这篇文章是关于 MySQL 的,尽管一般的事情可能适用于任何 DBMS。
  • 文中所写均为个人观点,并非最终真理。
  • 建议并不假装是新的,而是对文献阅读和个人经验进行概括的结果。
  • 在本文的框架内,我不会涉及 MySQL 配置问题。

使用MySQL时遇到的问题可以分为以下三组(按重要性排序):

  1. 不使用或滥用索引。
  2. 错误的数据库结构。
  3. 不正确\次优的 SQL 查询。

让我们仔细看看这些组中的每一个。

使用索引

不使用或滥用索引是最常减慢查询速度的原因。对于那些不熟悉索引工作机制或尚未阅读手册的人,我强烈建议您阅读它。

使用索引的提示:

  • 您不需要为所有内容编制索引。很多时候,人们在不理解其含义的情况下,只是简单地索引了一个表的所有字段。索引加快获取速度,但减慢行插入和更新速度,因此每个索引的选择必须有意义。
  • 表征索引的主要参数之一是选择性,即索引中不同元素的数量。索引具有两个或三个可能值的字段是没有意义的。这样的索引几乎没有什么好处。
  • 索引的选择应该从对给定表的所有查询的分析开始。通常,在这样的分析之后,您可以创建一个综合指数,而不是三个或四个指数。
  • 使用复合索引时,索引中字段的顺序很关键。
  • 不要忘记覆盖索引。如果查询中的所有数据都可以从索引中检索到,那么 MySQL 将不会直接访问该表。此类请求将很快执行。例如,对于SELECT name FROM user WHERE login='test'带有索引 (login, name) 的查询,不需要访问表。有时向复合索引添加一个额外的字段是有意义的,这将使索引覆盖并加快查询速度。
  • 对于行索引,通常只索引行的一部分就足够了。这可以显着减小索引大小。
  • 如果%在开头,则LIKE(SELECT * FROM table WHERE field LIKE '%test')不会使用索引。
  • FULLTEXT索引仅与MATCH ... AGAINST语法一起使用。

6.3 数据库结构

设计良好的数据库是快速高效地使用数据库的关键。另一方面,设计糟糕的数据库总是让开发人员头疼。

数据库设计技巧:

  1. 使用尽可能小的数据类型。数据类型越大,表越大,获取数据所需的磁盘访问次数就越多。使用一个非常方便的过程:SELECT * FROM table_name PROCEDURE ANALYSE();确定最小可能的数据类型。
  2. 在设计阶段观察正常形式。通常程序员在这个阶段已经求助于非规范化。然而,在大多数情况下,在项目开始时,结果如何会很不明显。对表进行非规范化比遭受次优非规范化的表要容易得多。有时JOIN它比不正确的非规范化表工作得更快。
  3. 不要使用NULL列,除非你有意识地需要它们。

6.4 SQL查询。

同样,人们常常希望用原生 SQL 重写所有查询,以便查询尽可能快。如果您决定这样做,那么这里有一些提示:

  1. 避免请求循环。SQL 是一种集合语言,编写查询不应使用函数语言,而应使用集合语言。
  2. 避免*在查询中使用(星号)。请随意准确列出您选择的字段。这将减少获取和发送的数据量。另外,不要忘记覆盖索引。即使您确实选择了表中的所有字段,也最好将它们列出来。首先,它提高了代码的可读性。使用星号时,不查看表是不可能知道表中有哪些字段的。其次,今天您的表有五个INT列,一个月后又添加了一个TEXTBLOB,星号保持原样。
  3. 分页时,要获取记录总数,请使用SQL_CALC_FOUND_ROWSSELECT FOUND_ROWS();使用时SQL_CALC_FOUND_ROWS MySQL缓存选定的行数(在应用 LIMIT 之前),并且在使用时SELECT FOUND_ROWS()仅返回此缓存值而无需重新执行查询。
  4. 不要忘记有INSERT多个插入的语法。一个查询将比循环中的多个查询快一个数量级。
  5. LIMIT在不需要所有数据的地方使用。
  6. 在选择之后代替INSERT… ON DUPLICATE KEY UPDATE…andINSERTUPDATE,通常代替REPLACE.
  7. 不要忘记这个惊人的功能GROUP_CONCAT。它可以帮助解决复杂的查询。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION