1)如果未使用索引,SQL查询执行时间O(n)是否与连接数相比较?如果没有,我们可能会期待什么样的关系?并且索引可以改善实际的大O时间复杂度,还是仅仅通过某个常数因子减少整个查询时间?
稍微含糊的问题,我确信它变化很大但我在这里谈论的是一般意义。
2)如果您有类似的查询:
SELECT T1.name, T2.date
FROM T1, T2
WHERE T1.id=T2.id
AND T1.color='red'
AND T2.type='CAR'
我是否正确假设DB在评估多表条件之前首先在T1.color和T2.type上进行单表过滤?在这种情况下,使查询更复杂可以使它更快,因为更少的行受到连接级别的测试?
答案 0 :(得分:44)
这取决于使用的查询计划。
即使没有索引,现代服务器也可以使用比HASH JOIN
更快的MERGE JOIN
和O(N * M)
更具体地说,HASH JOIN
的复杂性为O(N + M)
,其中N
是散列表,M
是查找表。散列和散列查找具有不变的复杂性。
MERGE JOIN
的复杂性为O(N*Log(N) + M*Log(M))
:它是对两个表进行排序的时间加上扫描它们的时间。
SELECT T1.name, T2.date
FROM T1, T2
WHERE T1.id=T2.id
AND T1.color='red'
AND T2.type='CAR'
如果没有定义索引,引擎将选择HASH JOIN
或MERGE JOIN
。
HASH JOIN
的工作原理如下:
选择散列表(通常是具有较少记录的表)。说它是t1
扫描t1
的所有记录。如果记录保持color='red'
,则此记录将进入哈希表,其中id
为关键字,name
为值。
扫描t2
的所有记录。如果记录保持type='CAR'
,则在哈希表中搜索其id
,并返回所有哈希命中的name
值以及当前值data
。< / p>
MERGE JOIN
的工作原理如下:
创建t1 (id, name)
的副本,按id
创建t2 (id, data)
的副本,按id
指针在两个表中都设置为最小值:
>1 2<
2 3
2 4
3 5
指针在循环中进行比较,如果匹配,则返回记录。如果它们不匹配,则具有最小值的指针会提前:
>1 2< - no match, left pointer is less. Advance left pointer
2 3
2 4
3 5
1 2< - match, return records and advance both pointers
>2 3
2 4
3 5
1 2 - match, return records and advance both pointers
2 3<
2 4
>3 5
1 2 - the left pointer is out of range, the query is over.
2 3
2 4<
3 5
>
在这种情况下,使查询更复杂可以使它更快,因为更少的行受到连接级别的测试?
不确定
没有WHERE
子句的查询:
SELECT T1.name, T2.date
FROM T1, T2
更简单但返回更多结果并运行更长时间。
答案 1 :(得分:15)
小心混淆太多不同的东西。根据要检查的行数,您有一个逻辑成本,基于实际返回的行数(可能)较小的逻辑成本,以及基于必须检查的页数的无关物理成本。
这三者是相关的,但并不强烈。
检查的行数是这些成本中最大的,并且最不容易控制。必须通过连接算法匹配行。这也是最不相关的。
返回的行数更加昂贵,因为它是客户端应用程序和数据库之间的I / O带宽。
读取的页数是最昂贵的,因为这是更多的物理I / O.这是最昂贵的,因为数据库中的负载会影响所有客户端。
一个表的SQL查询是 O ( n )。那是行数。根据页数,它也是 O ( p )。
对于多个表,检查的行是 O (n m ...)。这是嵌套循环算法。但是,根据关系的基数,结果集可能与 O ( n )一样小,因为关系都是1:1。但是必须检查每个表的匹配行。
散列连接用 O (n)直接散列查找替换 O (n * log(n))索引+表读取。您仍然需要处理 O ( n )行,但是您可以绕过一些索引读取。
合并连接用 O (log(n + m)(n + m))替换 O (n m)嵌套循环排序操作。
对于索引,如果仅检查表是否存在,则物理成本可能会降低为 O (log(n) m)。如果需要行,则索引会加快对行的访问,但必须处理所有匹配的行。 O (n m),因为这是结果集的大小,与索引无关。
根据索引的选择性,检查此工作的页面可能更小。
索引的重点不是减少检查的行数。这是为了减少获取行的物理I / O成本。
答案 2 :(得分:1)
如果未使用索引,SQL查询执行时间O(n)是否与连接数相比较?
通常它们将是O(n ^ m),其中n是每个表所涉及的记录数,m是要连接的表的数量。
并且索引可以改善实际的大O时间复杂度,还是仅仅通过某个常数因子减少整个查询时间?
两者。当连接被大量过滤时(即具有良好的WHERE子句),索引允许直接查找,并且当它们位于右列时,它们允许更快的连接。
当索引不在要加入或过滤的列上时,索引没有帮助。
答案 3 :(得分:0)
查看clustered与non-clustered indexes的工作方式
这是从纯粹的技术角度来看...为了一个简单的解释,我的好朋友mladen编写了一个简单的article to understand索引。
索引肯定有帮助,但我建议阅读以了解其优缺点。