我对数据库和SQL的了解大部分是基于大学课程。无论如何,我在一家正在使用数据库的公司里呆了几个月(差不多一年)。
我读过一些书,我已经在一些培训参加有关的数据库,例如MySQL
,PostgreSQL
,SQLite
,Oracle
和几个同样nonSQL
db
S,从而我们MongoDB
,Redis
,ElasticSearch
等。
就像我说的那样,我是乞gg,因为他缺乏很多知识,但是今天,有人告诉了我什么,这完全违背了我的乞gg的知识。
让我解释。让我们以SQL数据库为例,创建一个Person
内部表很少的简单表:
id | name | age
-----------------
1 | Alex | 24
2 | Brad | 34
3 | Chris | 29
4 | David | 28
5 | Eric | 18
6 | Fred | 42
7 | Greg | 65
8 | Hubert | 53
9 | Irvin | 17
10 | John | 19
11 | Karl | 23
现在,这是我要关注的部分- id
是INDEX
。
到目前为止,我认为它是以这种方式工作的:创建表时,该表INDEX
为空。当我向表中添加新记录时,INDEX
正在根据一些算法重新计算。例如:
一一分组:
1 ... N
N+1 ... 2N
...
XN+1 ... (X+1)N
所以,我以实例size = 11 elements
和N = 3
这将是这样的:
id | name | age
-----------------
1 | Alex | 24 // group0
2 | Brad | 34 // group0
3 | Chris | 29 // group0
4 | David | 28 // group1
5 | Eric | 18 // group1
6 | Fred | 42 // group1
7 | Greg | 65 // group2
8 | Hubert | 53 // group2
9 | Irvin | 17 // group2
10 | John | 19 // group3
11 | Karl | 23 // group3
因此,当我使用查询时SELECT * FROM Person WHERE id = 8
,它将进行一些简单的计算8 / 3 = 2
,因此我们必须在其中查找该对象group2
,然后将返回此行:
8 | Hubert | 53
这种方法可以在O(k)
哪里及时起作用k << size
。当然,以分组方式组织行的算法肯定要复杂得多,但是我认为这个简单的示例显示了我的观点。
所以现在,我想提出另一种方法,今天已经向我展示了这种方法。
让我们再次使用此表:
id | name | age
-----------------
1 | Alex | 24
2 | Brad | 34
3 | Chris | 29
4 | David | 28
5 | Eric | 18
6 | Fred | 42
7 | Greg | 65
8 | Hubert | 53
9 | Irvin | 17
10 | John | 19
11 | Karl | 23
现在,我们正在创建类似于Hashmap
(实际上,它实际上是一个哈希表)的东西,该映射id
到address
具有该ID的行。比方说:
id | addr
---------
1 | @0001
2 | @0010
3 | @0011
4 | @0100
5 | @0101
6 | @0110
7 | @0111
8 | @1000
9 | @1001
10 | @1010
11 | @1011
所以现在,当我运行查询时: SELECT * FROM Person WHERE id = 8
它将直接映射id = 8
到内存中的地址,并将返回该行。当然,这是复杂的O(1)
。
所以现在,我有几个问题。
1.两种解决方案的利弊是什么?
2.在当前的数据库实现中,哪一个最受欢迎?也许不同的数据库使用不同的方法?
3.它是否存在于非SQL数据库中?
先感谢您
比较
| B-tree | Hash Table
----------------------------------------------------
---------------- one element -------------------
----------------------------------------------------
SEARCHING | O(log(N)) | O(1) -> O(N)
DELETING | O(log(N)) | O(1) -> O(N)
INSERTING | O(log(N)) | O(1) -> O(N)
SPACE | O(N) | O(N)
----------------------------------------------------
---------------- k elements -------------------
----------------------------------------------------
SEARCHING | k + O(log(N)) | k * O(1) -> k * O(N)
DELETING | k + O(log(N)) | k * O(1) -> k * O(N)
INSERTING | k + O(log(N)) | k * O(1) -> k * O(N)
SPACE | O(N) | O(N)
N-记录数
我对吗?每次插入/删除后重建B树和哈希表的成本如何?对于B树,我们必须更改一些指针,但对于平衡B树,则需要更多的努力。同样在哈希表的情况下,我们必须要做很少的操作,特别是如果我们的操作产生冲突。
Of course, an alghoritm to organise rows in groups is for sure much more complicated but I think this simple example shows my point of view.
当然,我知道它要复杂得多。所以最后,当我在代码INDEX
中说出我的哪个解决方案(1st或2nd)更接近于此实际解决方案时?而基于的访问记录所需的时间呢INDEX
?是真的O(1)
吗 使用B树索引听起来很像O(log2(N))
。我对吗?
O(1)
你的部分是正确的!在第一种方式中,似乎您正在描述B树索引,但是您有一些误解。有没有计算(除以3或任何东西),这是因为树有多个级别(这是一棵树,它有大,小,小树枝,...,然后叶:)更复杂