在优化性能时,开发人员和架构师通常会忽略调整他们的 SQL 查询。了解数据库的工作原理和编写更好的 SQL 查询在提高性能方面发挥着巨大作用 。 高效的 SQL 查询意味着高质量、可扩展的应用程序。
技巧 1:为列选择合适的数据类型
SQL 中的每个表列都有一个关联的数据类型。您可以选择整数、日期、varchars、布尔值、文本等。开发时,选择正确的数据类型很重要。数字应该是数字类型,日期应该是日期等等,这对于索引是极其重要的。
让我们看看下面的例子。
SELECT employeeID, employeeName FROM employee WHERE employeeID = 13412; 复制代码
上面的[查询]获取 ID 为员工的员工 ID 和姓名13412
。如果 employeeID 的数据类型是字符串怎么办? 使用索引时您可能会遇到麻烦,因为当它应该是一个简单的扫描时,它会花费很长时间。
技巧 2:表变量和连接
当您有复杂的查询时,例如获取客户的订单以及他们的姓名和订单日期,您需要的不仅仅是一个简单的选择语句。在本例中,我们从客户和订单表中获取数据。这就是[加入]进来的地方。
让我们看一下连接的例子:
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate FROM Orders INNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID; 复制代码
SQL 提供
inner
、full
、left outer
和right outer
类型的联接。
表变量是临时存储数据的局部变量,具有局部变量的所有属性。不要在连接中使用表变量,因为 SQL 将它们视为单行。尽管它们速度很快,但表变量在连接中的表现并不好。
技巧 3:使用条件WHERE
从句
条件WHERE
子句用于子集化。假设您遇到这样的情况:
-if SEQ_VAR in (1, 2, 3) & diff(DATE_VAR2, DATE_VAR1)≥ 0 — elif SEQ_VAR in (4, 5, 6) & diff(DATE_VAR2, DATE_VAR1) ≥1 — else diff(DATE_VAR2, DATE_VAR1) ≥2 复制代码
使用条件WHERE
子句,它看起来像这样:
SELECT DAT.ID_VAR, DAT.SEQ_VAR, DAT.NUM_VAR, DATE_VAR1, DATE_VAR2, TRUNC(DATE_VAR2) - TRUNC(DATE_VAR1) AS LAG_IN_DATES FROM CURRENT_TABLE DAT WHERE (TRUNC(DATE_VAR2) - TRUNC(DATE_VAR1)) >= CASE WHEN SEQ_VAR IN (1,2,3) THEN 0 WHEN SEQ_VAR IN (4,5,6) THEN 1 ELSE 2 END ORDER BY ID_VAR, SEQ_VAR 复制代码
技巧 4:使用SET NOCOUNT ON
执行INSERT
、SELECT
、DELETE
和UPDATE
操作时,请使用SET NOCOUNT ON
。SQL 总是为此类操作返回受影响的行数,因此当您有包含大量连接的复杂查询时,它会影响性能。
使用SET NOCOUNT ON
,SQL 将不会计算受影响的行并提高性能。
在以下示例中,我们阻止显示有关受影响的行数的消息。
USE AdventureWorks2012; GO SET NOCOUNT OFF; GO -- Display the count message. SELECT TOP(5)LastName FROM Person.Person WHERE LastName LIKE 'A%'; GO -- SET NOCOUNT to ON to no longer display the count message. SET NOCOUNT ON; GO SELECT TOP(5) LastName FROM Person.Person WHERE LastName LIKE 'A%'; GO -- Reset SET NOCOUNT to OFF SET NOCOUNT OFF; GO 复制代码
提示 5:避免ORDER BY
、GROUP BY
和DISTINCT
仅在必要时使用ORDER BY
、GROUP BY
和。DISTINCT
SQL 创建工作表并将数据放在那里。然后它根据查询组织工作表中的数据,然后返回结果。
技巧 6:完全限定数据库对象名称
使用完全限定的数据库对象名称的目的是消除歧义。完全限定的对象名称如下所示:
DATABASE.SCHEMA.OBJECTNAME. 复制代码
当您有权访问多个数据库、模式和表时,指定要访问的内容就变得很重要。除非您正在使用具有多个用户和模式的大型数据库,否则您不需要这样做,但这是一个很好的做法。
所以不要使用像这样的语句:
SELECT * FROM TableName 复制代码
你应该使用:
SELECT * FROM dbo.TableName 复制代码
技巧 7:了解如何完全保护您的代码
数据库存储各种信息,使它们成为主要的攻击目标。常见的攻击包括[SQL 注入] ,用户输入 SQL 语句而不是用户名并检索或修改您的数据库。SQL注入的例子包括:
textuserID = getRequestString("userID"); textSQL = "SELECT * FROM Users WHERE userID = " + textuserID; 复制代码
假设你有这个,textuserID
将从用户那里获取输入。这是它可能出错的原因:
SELECT * FROM Users WHERE userID = 890 OR 1=1; 复制代码
由于1=1
始终为真,它将从 Users 表中获取所有数据。
您可以使用参数化语句、输入验证、清理输入等来保护您的数据库免受 SQL 注入攻击。如何保护您的数据库取决于 DBMS。您需要了解您的 DBMS 及其安全问题,这样您才能编写安全的代码。