sql 优化

  1. SELECT语句中“ *”的用法

除非它是强制性的,否则不要使用“ ”功能,因为它效率很低。在SELECT语句中使用实际的列名而不是'“,则我们的查询实际上变得更快。

常用方法:

SELECT * FROM EmployeeDetails

更好的方法:

SELECT EmpNo,Name,Department FROM EmployeeDetails
2. 使用TRUNCATE而不是DELETE

当我们不需要撤消信息时,使用TRUNCATE而不是DELETE来擦除小型或大型表的内容。

  1. 使用表别名

当一个查询涉及多个表时,建议使用表别名,并在所有列名前加上别名。这将

  1. 减少解析时间
  2. 我们可以避免使用歧义命名的列时可能发生的意外语法错误。
  3. 通配符的用法

我们使用带'%'符号的通配符。当使用通配符时,特别是在使用很大的表时,它会降低查询性能。因此,我们可以使用后缀通配符而不是前缀或完整通配符来优化涉及通配符的查询。

例:

使用完整通配符查询:SELECT * FROM Student WHERE first_name LIKE'%mark%'
使用前缀通配符查询:SELECT * FROM Student WHERE first_name LIKE'%mark'

使用后缀通配符查询:SELECT * FROM Student WHERE first_name LIKE'mark%'

  1. 使用WHERE代替HAVING

选择所有行后,使用Haven子句过滤行。它就像一个过滤器。仅在获取所有行之后,HAVING子句才会过滤选定的行。这可能包括排序,求和等。通过WHERE子句而不是HAVING子句限制行有助于减少这些开销。

常用方法:

SELECT dept_name,COUNT(dept_id)
FROM department
GROUP BY dept_name
HAVING dept_name != ‘DEV’
AND dept_name != ‘IVS’

更好的方法:

SELECT dept_name,COUNT(dept_id)
FROM department
GROUP BY dept_name
WHERE dept_name != ‘DEV’
AND dept_name != ‘IVS’

  1. WHERE子句中条件的使用

小号OME凡在SELECT语句的子句不使用索引。!=函数不使用索引。所有对NOT的引用!=和<>禁用索引使用。因此,它会影响性能。

常用方法:

SELECT OrderNumber
FROM Order
WHERE TotalAmount !=0

更好的方法:

SELECT OrderNumber
FROM Order
WHERE TotalAmount > 0

常用方法:

SELECT empid,firstname,age
FROM employee
WHERE SUBSTR(firstname,1,3) = ‘Alb’

更好的方法:

SELECT empid,firstname,age
FROM employee
WHERE firstname LIKE ‘Alb%’

  1. 联接在WHERE子句中的位置

由于解析是从BOTTOM到TOP进行的,因此应该先编写表联接,然后再执行WHERE子句的任何条件,并在联接完成后将筛选出最大记录的条件放在最后。

通过应用适当的过滤器(如果有)来减少参与联接的表中的行数。这将帮助优化器有效地使用缓存并帮助提高性能

将具有高容量的表放在SQL查询的右侧。

常用方法:

SELECT emp_id
FROM employee e
WHERE sal > 50000
AND job = ‘MANAGER’
AND 25 < (SELECT COUNT(*)
FROM employee
WHERE mgr_id = e.emp_id)

更好的方法:

SELECT emp_id
FROM employee e
WHERE 25 < (SELECT COUNT(*)
FROM employee
WHERE mgr_id = e.emp_id)
AND
Sal > 50000
AND
Job = ‘MANAGER’

  1. 有效使用GROUP BY子句

我们可以通过在选择过程的早期删除不需要的(不需要的)行来提高涉及GROUP BY子句的查询的性能。

常用方法:

SELECT job, AVG(sal)
FROM employee
GROUP BY job
HAVING job = ‘PRESIDENT’
OR job = ‘MANAGER’

更好的方法:

SELECT job, AVG(sal)
FROM employee
WHERE job = ‘PRESIDENT’
OR job = ‘MANAGER’
GROUP BY job

  1. 使用UNION ALL代替UNION

如果可能的话,我们应该使用UNION ALL而不是UNION,因为它可以提高查询的性能。

常用方法:

SELECT studentid,firstname,subject
FROM studentdetails
UNION
SELECT studentid,firstname
FROM sportsteam

更好的方法:

SELECT studentid,firstname,subject
FROM studentdetails
UNION ALL
SELECT studentid,firstname
FROM sportsteam

  1. 优化子查询性能

有时我们的主查询中可能有多个子查询。 我们应该尽量减少查询中子查询块的数量。 主查询中子查询的数量越多,性能越差。

  1. 使用“ EXISTS”,“ IN”和表联接

  2. 通常,IN性能最慢。

  3. 当大多数过滤条件都在子查询中时,IN很有效

  4. 当大多数过滤条件位于主查询中时,EXIST效率很高。

常用方法:

SELECT firstname
FROM employee e
WHERE EXISTS (SELECT deptname
FROM department
WHERE deptid = e.deptid
AND deptcat = ‘A’)

更好的方法:

SELECT firstname
FROM department d, employee e
WHERE e.deptid = d.deptid
AND deptcat = ‘A’

  1. sql 在not in 子查询有null值情况下经常出现的陷阱

–如果null参与算术运算,则该算术表达式的值为null。(例如:+,-,*,/ 加减乘除)

–如果null参与比较运算,则结果可视为false。(例如:>=,<=,<> 大于,小于,不等于)

–如果null参与聚集运算,则聚集函数都置为null(使用isnull(字段,0)等方式可以避免这种情况)。除count(*), count(1), count(0)等之外(count(字段) 字段为null的行不参与计数)。

--如果在not in子查询中有null值的时候,则不会返回数据。 (最简单的解释请参考下面的评论说明)

SELECT *
FROM dbo.Table_A AS a
WHERE a.ID NOT IN ( SELECT b.ID
FROM dbo.Table_B AS b)

   --正确写法                      

SELECT *
FROM dbo.Table_A AS a
WHERE a.ID NOT IN ( SELECT b.ID
FROM dbo.Table_B AS b
WHERE b.ID IS NOT NULL ) --排除NULL值参与运算符比较

--建议修改为关联查询方法
--正确写法1
SELECT *
FROM dbo.Table_A AS a
WHERE NOT EXISTS ( SELECT *
FROM dbo.Table_B AS b
WHERE a.ID = b.ID )
--正确写法2
SELECT *
FROM dbo.Table_A AS a
LEFT OUTER JOIN dbo.Table_B AS b ON a.ID = b.ID
WHERE b.ID IS NULL

  1. EXISTS应该始终比DISTINCT更受青睐

当您使用涉及具有一对多关系的表的JOINS时,应始终以EXISTS优先于DISTINCT

常用方法:

SELECT DISTINCT deptid,deptname
FROM department d, employee e
WHERE d.deptid = e.deptid

更好的方法:

SELECT deptid,deptname
FROM department d
WHERE EXISTS (SELECT firstname FROM employee e WHERE e.deptid = d.deptid)

  1. 索引创建

索引通过指针创建到数据的直接路径,从而允许更有效地访问表中的行。因此,索引是一个或多个键的集合,每个键都指向表中的行。创建后,将对其进行维护。在键值上建立的索引可以被应用程序直接用于访问表中的行,而不是基于键值对行进行随机访问。这很重要,因为基表中行的物理存储未排序。

索引主要用于频繁搜索的列。因此,应创建索引,以防频繁搜索列/表。如果对表/列的搜索很少,那么最好不要在其上具有索引,因为使用索引更新表将花费更多时间。这是因为索引也将需要更新。

  1. 使用OR时请注意运动

使用OR条件时请多加注意。正如我们在公司网站中看到的那样,使用OR谓词以某种方式阻止了SQL优化器正确使用索引。

  1. 常量的用法

在过滤器和联接中对表达式的LHS使用常量。例如,使用where 1 = Flag代替Where Flag = 1 。

  1. 临时表的用法

在执行一些复杂的操作时,请使用Temp表。使用Temp表比使用table变量的优势在于我们可以创建索引。

  1.    Usage of Transactions
    

在SQL查询或存储过程中使用BEGIN和END TRANSACTION时要格外小心。 它将锁定表,直到事务完成。 因此,在使用前请与建筑师团队讨论。。

  1. 游标的用法

避免使用游标,因为不建议这样做。而是尝试通过其他可能的选项来实现功能。如果确实需要使用游标,请与架构师小组讨论并获得批准。

  1. 授予权限的使用

授予所需权限的声明应包含在SP,Function等数据库对象中。截断,创建或删除数据库对象时应格外小心。 开发人员应注意恢复这些必需的权限。。

  1. 触发器的使用

避免使用触发器,因为不建议这样做。如果确实需要使用游标,请与架构师小组讨论并获得批准。

  1. 将可重用查询编写为函数

开发人员在设计SQL解决方案时应考虑可重用性方面。所有可重用的逻辑都应编写为函数,因此可以重用。

  1. 视图的使用

使用视图时请多加注意。 视图创建表的外观,但是DBMS仍必须将针对视图的查询转换为针对基础源表的查询。 如果视图是由复杂的多表查询定义的,则对视图的简单查询可能会花费大量时间

当用户尝试更新视图的行时,DBMS必须将请求转换为对基础源表的行的更新。 对于简单视图来说,这是可能的,但更复杂的视图通常仅限于只读。 在使用“视图”之前,请与建筑师团队讨论。

posted @ 2021-01-04 15:37  王哲66369  阅读(93)  评论(0编辑  收藏  举报