6.1 简介
现在让我们从理论转向实践。
我们生活在现实世界中,所有的软件产品最终都是为活着的人创造的。这些活着的人对加载缓慢的网站和运行缓慢的程序感到非常恼火。
而如果一个数据库查询花费的时间超过一秒,这是不可接受的。用户根本不会使用页面/功能如此缓慢的产品。
但通常,为了显示一个页面,您需要对数据库执行几十次查询。如果它们是按顺序执行的,那么您将不再有第二个限制,但假设每个请求 100 毫秒。
以下是程序员加速数据库查询的前 5 种方法:
- 为数据库中的表添加索引。
- 重写和优化查询。
- 在数据库端启用(和配置)缓存。
- 在客户端启用缓存。
- 执行数据库反规范化。
大多数情况下,您已经熟悉了所有这些内容,因此以下内容只是实用建议。
6.2 指数
众所周知,使用数据库占据了几乎所有站点的大部分工作。它正在处理最常成为 Web 应用程序瓶颈的数据库。
在本文中,我想提供有关使用 MySQL 的实用建议。
我马上说:
- 这篇文章是关于 MySQL 的,尽管一般的事情可能适用于任何 DBMS。
- 文中所写均为个人观点,并非最终真理。
- 建议并不假装是新的,而是对文献阅读和个人经验进行概括的结果。
- 在本文的框架内,我不会涉及 MySQL 配置问题。
使用MySQL时遇到的问题可以分为以下三组(按重要性排序):
- 不使用或滥用索引。
- 错误的数据库结构。
- 不正确\次优的 SQL 查询。
让我们仔细看看这些组中的每一个。
使用索引
不使用或滥用索引是最常减慢查询速度的原因。对于那些不熟悉索引工作机制或尚未阅读手册的人,我强烈建议您阅读它。
使用索引的提示:
- 您不需要为所有内容编制索引。很多时候,人们在不理解其含义的情况下,只是简单地索引了一个表的所有字段。索引加快获取速度,但减慢行插入和更新速度,因此每个索引的选择必须有意义。
- 表征索引的主要参数之一是选择性,即索引中不同元素的数量。索引具有两个或三个可能值的字段是没有意义的。这样的索引几乎没有什么好处。
- 索引的选择应该从对给定表的所有查询的分析开始。通常,在这样的分析之后,您可以创建一个综合指数,而不是三个或四个指数。
- 使用复合索引时,索引中字段的顺序很关键。
- 不要忘记覆盖索引。如果查询中的所有数据都可以从索引中检索到,那么 MySQL 将不会直接访问该表。此类请求将很快执行。例如,对于
SELECT name FROM user WHERE login='test'
带有索引 (login, name) 的查询,不需要访问表。有时向复合索引添加一个额外的字段是有意义的,这将使索引覆盖并加快查询速度。 - 对于行索引,通常只索引行的一部分就足够了。这可以显着减小索引大小。
- 如果
%
在开头,则LIKE(SELECT * FROM table WHERE field LIKE '%test')
不会使用索引。 - FULLTEXT索引仅与MATCH ... AGAINST语法一起使用。
6.3 数据库结构
设计良好的数据库是快速高效地使用数据库的关键。另一方面,设计糟糕的数据库总是让开发人员头疼。
数据库设计技巧:
- 使用尽可能小的数据类型。数据类型越大,表越大,获取数据所需的磁盘访问次数就越多。使用一个非常方便的过程:
SELECT * FROM table_name PROCEDURE ANALYSE();
确定最小可能的数据类型。 - 在设计阶段观察正常形式。通常程序员在这个阶段已经求助于非规范化。然而,在大多数情况下,在项目开始时,结果如何会很不明显。对表进行非规范化比遭受次优非规范化的表要容易得多。有时
JOIN
它比不正确的非规范化表工作得更快。 - 不要使用
NULL
列,除非你有意识地需要它们。
6.4 SQL查询。
同样,人们常常希望用原生 SQL 重写所有查询,以便查询尽可能快。如果您决定这样做,那么这里有一些提示:
- 避免请求循环。SQL 是一种集合语言,编写查询不应使用函数语言,而应使用集合语言。
- 避免
*
在查询中使用(星号)。请随意准确列出您选择的字段。这将减少获取和发送的数据量。另外,不要忘记覆盖索引。即使您确实选择了表中的所有字段,也最好将它们列出来。首先,它提高了代码的可读性。使用星号时,不查看表是不可能知道表中有哪些字段的。其次,今天您的表有五个INT列,一个月后又添加了一个TEXT和BLOB,星号保持原样。 - 分页时,要获取记录总数,请使用
SQL_CALC_FOUND_ROWS
和SELECT FOUND_ROWS();
使用时SQL_CALC_FOUND_ROWS MySQL
缓存选定的行数(在应用 LIMIT 之前),并且在使用时SELECT FOUND_ROWS()
仅返回此缓存值而无需重新执行查询。 - 不要忘记有
INSERT
多个插入的语法。一个查询将比循环中的多个查询快一个数量级。 LIMIT
在不需要所有数据的地方使用。- 在选择之后代替
INSERT… ON DUPLICATE KEY UPDATE…
andINSERT
或UPDATE
,通常代替REPLACE
. - 不要忘记这个惊人的功能
GROUP_CONCAT
。它可以帮助解决复杂的查询。
GO TO FULL VERSION