我正在尝试优化长查询并提高其可读性。 使用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秒。在可读性方面,我更喜欢第一个查询,但就性能而言,我更喜欢第二个查询。但是,如果查询太长,这是要执行的建议查询?
答案 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);