使用' WHERE'进行SQL查询优化'和'子句

时间:2018-04-10 08:36:36

标签: sql sql-server query-optimization where-clause

我正在尝试优化长查询并提高其可读性。 使用AND关键字的WHERE子句是否正确读取索引或影响读取的性能?

实施例: 表tblTransactions包含61,795条记录

DECLARE @DateTypeId INT = 1 
DECLARE @FromDate DATETIME = '01/01/2000' 
DECLARE @ToDate DATETIME = '01/01/2019'

SELECT *
FROM tblTransactions ts
WHERE (((ts.TransactionDate BETWEEN @FromDate AND @ToDate) AND @DateTypeId = 1)
        OR ((ts.PostingDate BETWEEN @FromDate AND @ToDate) AND @DateTypeId = 2))

执行的总时间 9秒。这是查询的另一个例子。

DECLARE @DateTypeId INT = 1
DECLARE @FromDate DATETIME = '01/01/2000'
DECLARE @ToDate DATETIME = '01/01/2019'

IF @DateTypeId = 1
    SELECT *
    FROM tblTransactions ts
    WHERE ts.TransactionDate BETWEEN @FromDate AND @ToDate

ELSE IF @DateTypeId = 2
    SELECT *
    FROM tblTransactions ts
    WHERE ts.PostingDate BETWEEN @FromDate AND @ToDate

此查询的执行时间为 8 - 9秒。在可读性方面,我更喜欢第一个查询,但就性能而言,我更喜欢第二个查询。但是,如果查询太长,这是要执行的建议查询?

3 个答案:

答案 0 :(得分:0)

优化是一项微妙的任务。它在很大程度上取决于受试者的多方面。

了解表结构(列,数据,索引)非常重要, 了解您要执行的查询(选择和连接中的列和/或涉及的函数)非常重要。

我们还应该谈谈你的硬件和你的sql-server版本,但它将成为一个非常深入的分析..

让我们试着简化一下。

如果你的索引对于检索选定的列没有用(我不是在讨论过滤行),优化器将(几乎)不使用它们,它将直接在聚簇索引上进行全表扫描(你必须在至少这个)。

如果您的选择与问题(d = {'+': (lambda x: x[1] + x[2]), '-': (lambda x: x[1] - x[2])} def calculator(x, d): return d[x[0]](x) print(calculator(["+",2,3], d)) # 5 )一样简单,那么我们必须考虑表结构。

所以,重点是,如果你只选择几列,你可以建立一个包含这些列的索引,它将被使用,你会很高兴(当然?)。

当您在索引中包含列时,它们不是索引键的一部分,而是仅用作有效负载数据。

问题在于包含列,在索引中占用的空间与表中的空间一样多。所以如果你有数千条带有大列的记录,你将为所涉及的数据复制产生巨大的索引。

在完成所有这些考虑后,您可以构建您的超级索引,包括所有选定的列..也许您可以发现总查询执行时间几乎相同..

花费的大部分时间不是要查找要提取的数据,而是要检索I / O操作并将它们放入输出中。

好的,现在有一些建议和选择:

1)我将保留<?php include 'dbconnect.php'; $result = mysqli_query($link, "SELECT * FROM city where district_id='$dist' "); $str = ''; while($city_row=mysqli_fetch_array($result)){ $str .= '<input type="checkbox" value="'.$city_row['id'].'"/>'.$city_row['city_name']; } echo $str; ?> 版本,越简单就越好..

2)尝试使用select * from tblTransactions中包含的列添加索引(使用您的姓名..)并运行查询,检查它们是否已被使用以及是否有性能提升

IF/ELSE

3)您可以尝试混合解决方案,更简单的索引和棘手的查询

SELECT

以上每一项都是为了测试...而且(也许)它可能没用..

我希望了解一点,优化的重大问题是有用的。

答案 1 :(得分:-1)

请尝试获得更好的表现:

 DECLARE @DateTypeId INT = 1
 DECLARE @FromDate DATETIME = '01/01/2000'
 DECLARE @ToDate DATETIME = '01/01/2019'

 IF @DateTypeId = 1
 SELECT *
 FROM tblTransactions ts
 WHERE  @FromDate >= ts.TransactionDate <= @ToDate

 ELSE IF @DateTypeId = 2
 SELECT *
 FROM tblTransactions ts
 WHERE  @FromDate >= ts.PostingDate <= @ToDate

答案 2 :(得分:-1)

由于单独的查询与组合查询一样长,我会留在组合查询中(即您也喜欢的第一个查询)。

您的查询中唯一的标准是日期,在一个案例TransactionDate中,在另一个PostingDate中。确保你有单独的索引,以便为DBMS提供在那里查找日期范围的选项:

create index idx_transact_transaction_date on tbltransactions(transactiondate);
create index idx_transact_posting_date on tbltransactions(postingdate);