自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

用Python寫一個(gè)NoSQL數(shù)據(jù)庫

開發(fā) 后端 其他數(shù)據(jù)庫
在本文, 我們將會(huì)通過純 Python (我比較喜歡叫它, “輕結(jié)構(gòu)化的偽代碼”) 寫一個(gè) NoSQL 數(shù)據(jù)庫來回答這些問題。

 NoSQL 這個(gè)詞在近些年正變得隨處可見. 但是到底 “NoSQL” 指的是什么? 它是如何并且為什么這么有用? 在本文, 我們將會(huì)通過純 Python (我比較喜歡叫它, “輕結(jié)構(gòu)化的偽代碼”) 寫一個(gè) NoSQL 數(shù)據(jù)庫來回答這些問題.

[[399458]]

OldSQL

很多情況下, SQL 已經(jīng)成為 “數(shù)據(jù)庫” (database) 的一個(gè)同義詞. 實(shí)際上, SQL 是 Strctured Query Language 的首字母縮寫, 而并非指數(shù)據(jù)庫技術(shù)本身. 更確切地說, 它所指的是從 RDBMS (關(guān)系型數(shù)據(jù)庫管理系統(tǒng), Relational Database Management System ) 中檢索數(shù)據(jù)的一門語言. MySQL, MS SQL Server 和 Oracle 都屬于 RDBMS 的其中一員.

RDBMS 中的 R, 即 “Relational” (有關(guān)系,關(guān)聯(lián)的), 是其中內(nèi)容最豐富的部分. 數(shù)據(jù)通過 表 (table) 進(jìn)行組織, 每張表都是一些由 類型 (type) 相關(guān)聯(lián)的列 (column) 構(gòu)成. 所有表, 列及其類的類型被稱為數(shù)據(jù)庫的 schema (架構(gòu)或模式). schema 通過每張表的描述信息完整刻畫了數(shù)據(jù)庫的結(jié)構(gòu). 比如, 一張叫做 Car 的表可能有以下一些列:

  •  Make: a string
  •  Model: a string
  •  Year: a four-digit number; alternatively, a date
  •  Color: a string
  •  VIN(Vehicle Identification Number): a string

在一張表中, 每個(gè)單一的條目叫做一 行 (row), 或者一條 記錄 (record). 為了區(qū)分每條記錄, 通常會(huì)定義一個(gè) 主鍵 (primary key). 表中的 主鍵 是其中一列 , 它能夠唯一標(biāo)識每一行. 在表 Car 中, VIN 是一個(gè)天然的主鍵選擇, 因?yàn)樗軌虮WC每輛車具有唯一的標(biāo)識. 兩個(gè)不同的行可能會(huì)在 Make, Model, Year 和 Color 列上有相同的值, 但是對于不同的車而言, 肯定會(huì)有不同的 VIN. 反之, 只要兩行擁有同一個(gè) VIN, 我們不必去檢查其他列就可以認(rèn)為這兩行指的的就是同一輛車.

Querying

SQL 能夠讓我們通過對數(shù)據(jù)庫進(jìn)行 query (查詢) 來獲取有用的信息. 查詢 簡單來說, 查詢就是用一個(gè)結(jié)構(gòu)化語言向 RDBMS 提問, 并將其返回的行解釋為問題的答案. 假設(shè)數(shù)據(jù)庫表示了美國所有的注冊車輛, 為了獲取 所有的 記錄, 我們可以通過在數(shù)據(jù)庫上進(jìn)行如下的 SQL 查詢 :

將 SQL 大致翻譯成中文:

  •  “SELECT”: “向我展示”
  •  “Make, Model”: “Make 和 Model 的值”
  •  “FROM Car”: “對表 Car 中的每一行”

也就是, “向我展示表 Car 每一行中 Make 和 Model 的值”. 執(zhí)行查詢后, 我們將會(huì)得到一些查詢的結(jié)果, 其中每個(gè)都是 Make 和 Model. 如果我們僅關(guān)心在 1994 年注冊的車的顏色, 那么可以:

此時(shí), 我們會(huì)得到一個(gè)類似如下的列表:

最后, 我們可以通過使用表的 (primary key) 主鍵 , 這里就是 VIN 來指定查詢一輛車:

上面這條查詢語句會(huì)返回所指定車輛的屬性信息.

主鍵被定義為唯一不可重復(fù)的. 也就是說, 帶有某一指定 VIN 的車輛在表中至多只能出現(xiàn)一次. 這一點(diǎn)非常重要,為什么? 來看一個(gè)例子:

Relations

假設(shè)我們正在經(jīng)營一個(gè)汽車修理的業(yè)務(wù). 除了其他一些必要的事情, 我們還需要追蹤一輛車的服務(wù)歷史, 即在該輛車上所有的修整記錄. 那么我們可能會(huì)創(chuàng)建包含以下一些列的 ServiceHistory 表:

VIN | Make | Model | Year | Color | Service Performed | Mechanic | Price | Date

這樣, 每次當(dāng)車輛維修以后, 我們就在表中添加新的一行, 并寫入該次服務(wù)我們做了一些什么事情, 是哪位維修工, 花費(fèi)多少和服務(wù)時(shí)間等.

但是等一下, 我們都知道,對于同一輛車而言,所有車輛自身信息有關(guān)的列是不變的。也就是說,如果把我的 Black 2014 Lexus RX 350 修整 10 次的話, 那么即使 Make, Model, Year 和 Color 這些信息并不會(huì)改變,每一次仍然重復(fù)記錄了這些信息. 與無效的重復(fù)記錄相比, 一個(gè)更合理的做法是對此類信息只存儲一次, 并在有需要的時(shí)候進(jìn)行查詢。

那么該怎么做呢?我們可以創(chuàng)建第二張表:Vehicle , 它有如下一些列:

VIN | Make | Model | Year | Color

這樣一來, 對于 ServiceHistory 表, 我們可以精簡為如下一些列:

VIN | Service Performed | Mechanic | Price | Date

你可能會(huì)問,為什么 VIN 會(huì)在兩張表中同時(shí)出現(xiàn)?因?yàn)槲覀冃枰幸粋€(gè)方式來確認(rèn)在 ServiceHistory 表的 這 輛車指的就是 Vehicle 表中的 那 輛車, 也就是需要確認(rèn)兩張表中的兩條記錄所表示的是同一輛車。這樣的話,我們僅需要為每輛車的自身信息存儲一次即可. 每次當(dāng)車輛過來維修的時(shí)候, 我們就在 ServiceHistory 表中創(chuàng)建新的一行, 而不必在 Vehicle 表中添加新的記錄。畢竟, 它們指的是同一輛車。

我們可以通過 SQL 查詢語句來展開 Vehicle 與 ServiceHistory 兩張表中包含的隱式關(guān)系:

該查詢旨在查找維修費(fèi)用大于 $75.00 的所有車輛的 Model 和 Year. 注意到我們是通過匹配 Vehicle 與 ServiceHistory 表中的 VIN 值來篩選滿足條件的記錄. 返回的將是兩張表中符合條件的一些記錄, 而 “Vehicle.Model” 與 “Vehicle.Year” , 表示我們只想要 Vehicle 表中的這兩列.

如果我們的數(shù)據(jù)庫沒有 索引 (indexes) (正確的應(yīng)該是 indices), 上面的查詢就需要執(zhí)行 表掃描 (table scan) 來定位匹配查詢要求的行。table scan 是按照順序?qū)Ρ碇械拿恳恍羞M(jìn)行依次檢查, 而這通常會(huì)非常的慢。實(shí)際上, table scan 實(shí)際上是所有查詢中最慢的。

可以通過對列加索引來避免掃描表。我們可以把索引看做一種數(shù)據(jù)結(jié)構(gòu), 它能夠通過預(yù)排序讓我們在被索引的列上快速地找到一個(gè)指定的值 (或指定范圍內(nèi)的一些值). 也就是說, 如果我們在 Price 列上有一個(gè)索引, 那么就不需要一行一行地對整個(gè)表進(jìn)行掃描來判斷其價(jià)格是否大于 75.00, 而是只需要使用包含在索引中的信息 “跳” 到第一個(gè)價(jià)格高于 75.00 的那一行, 并返回隨后的每一行(由于索引是有序的, 因此這些行的價(jià)格至少是 75.00)。

當(dāng)應(yīng)對大量的數(shù)據(jù)時(shí), 索引是提高查詢速度不可或缺的一個(gè)工具。當(dāng)然, 跟所有的事情一樣,有得必有失, 使用索引會(huì)導(dǎo)致一些額外的消耗:索引的數(shù)據(jù)結(jié)構(gòu)會(huì)消耗內(nèi)存,而這些內(nèi)存本可用于數(shù)據(jù)庫中存儲數(shù)據(jù)。這就需要我們權(quán)衡其利弊,尋求一個(gè)折中的辦法, 但是為經(jīng)常查詢的列加索引是 非常 常見的做法。

The Clear Box

得益于數(shù)據(jù)庫能夠檢查一張表的 schema (描述了每列包含了什么類型的數(shù)據(jù)), 像索引這樣的高級特性才能夠?qū)崿F(xiàn), 并且能夠基于數(shù)據(jù)做出一個(gè)合理的決策。也就是說, 對于一個(gè)數(shù)據(jù)庫而言, 一張表其實(shí)是一個(gè) “黑盒” (或者說透明的盒子) 的反義詞?

當(dāng)我們談到 NoSQL 數(shù)據(jù)庫的時(shí)候要牢牢記住這一點(diǎn)。當(dāng)涉及 query 不同類型數(shù)據(jù)庫引擎的能力時(shí), 這也是其中非常重要的一部分。

Schemas

我們已經(jīng)知道, 一張表的 schema , 描述了列的名字及其所包含數(shù)據(jù)的類型。它還包括了其他一些信息, 比如哪些列可以為空, 哪些列不允許有重復(fù)值, 以及其他對表中列的所有限制信息。在任意時(shí)刻一張表只能有一個(gè) schema, 并且 表中的所有行必須遵守 schema 的規(guī)定 。

這是一個(gè)非常重要的約束條件。假設(shè)你有一張數(shù)據(jù)庫的表, 里面有數(shù)以百萬計(jì)的消費(fèi)者信息。你的銷售團(tuán)隊(duì)想要添加額外的一些信息 (比如, 用戶的年齡), 以期提高他們郵件營銷算法的準(zhǔn)確度。這就需要來 alter (更改) 現(xiàn)有的表 – 添加新的一列。我們還需要決定是否表中的每一行都要求該列必須有一個(gè)值。通常情況下, 讓一個(gè)列有值是十分有道理的, 但是這么做的話可能會(huì)需要一些我們無法輕易獲得的信息(比如數(shù)據(jù)庫中每個(gè)用戶的年齡)。因此在這個(gè)層面上,也需要有些權(quán)衡之策。

此外,對一個(gè)大型數(shù)據(jù)庫做一些改變通常并不是一件小事。為了以防出現(xiàn)錯(cuò)誤,有一個(gè)回滾方案非常重要。但即使是如此,一旦當(dāng) schema 做出改變后,我們也并不總是能夠撤銷這些變動(dòng)。schema 的維護(hù)可能是 DBA 工作中最困難的部分之一。

Key/Value Stores

在 “NoSQL” 這個(gè)詞存在前, 像 memcached 這樣的 鍵/值 數(shù)據(jù)存儲 (Key/Value Data Stores) 無須 table schema 也可提供數(shù)據(jù)存儲的功能。實(shí)際上, 在 K/V 存儲時(shí), 根本沒有 “表 (table)” 的概念。只有 鍵 (keys) 與 值 (values) . 如果鍵值存儲聽起來比較熟悉的話, 那可能是因?yàn)檫@個(gè)概念的構(gòu)建原則與 Python 的 dict 與 set 相一致: 使用 hash table (哈希表) 來提供基于鍵的快速數(shù)據(jù)查詢。一個(gè)基于 Python 的最原始的 NoSQL 數(shù)據(jù)庫, 簡單來說就是一個(gè)大的字典 (dictionary) .

為了理解它的工作原理,親自動(dòng)手寫一個(gè)吧!首先來看一下一些簡單的設(shè)計(jì)想法:

  •  一個(gè) Python 的 dict 作為主要的數(shù)據(jù)存儲
  •  僅支持 string 類型作為鍵 (key)
  •  支持存儲 integer, string 和 list
  •  一個(gè)使用 ASCLL string 的簡單 TCP/IP 服務(wù)器用來傳遞消息
  •  一些像 INCREMENT, DELETE , APPEND 和 STATS 這樣的高級命令 (command)

有一個(gè)基于 ASCII 的 TCP/IP 接口的數(shù)據(jù)存儲有一個(gè)好處, 那就是我們使用簡單的 telnet 程序即可與服務(wù)器進(jìn)行交互, 并不需要特殊的客戶端 (盡管這是一個(gè)非常好的練習(xí)并且只需要 15 行代碼即可完成)。

對于我們發(fā)送到服務(wù)器及其它的返回信息,我們需要一個(gè) “有線格式”。下面是一個(gè)簡單的說明:

Commands Supported

  •  PUT

參數(shù):Key, Value

目的:向數(shù)據(jù)庫中插入一條新的條目 (entry)

  •  GET

參數(shù):Key

目的:從數(shù)據(jù)庫中檢索一個(gè)已存儲的值

  •  PUTLIST

參數(shù):Key, Value

目的:向數(shù)據(jù)庫中插入一個(gè)新的列表?xiàng)l目

  •  APPEND

參數(shù):Key, Value

目的:向數(shù)據(jù)庫中一個(gè)已有的列表添加一個(gè)新的元素

  •  INCREMENT

參數(shù):key

目的:增長數(shù)據(jù)庫的中一個(gè)整型值

  • DELETE

參數(shù):Key

目的:從數(shù)據(jù)庫中刪除一個(gè)條目

  •  STATS

參數(shù):無 (N/A)

目的:請求每個(gè)執(zhí)行命令的 成功/失敗 的統(tǒng)計(jì)信息

現(xiàn)在我們來定義消息的自身結(jié)構(gòu)。

Message Structure

1.Request Messages

一條 請求消息 (Request Message) 包含了一個(gè)命令(command),一個(gè)鍵 (key), 一個(gè)值 (value), 一個(gè)值的類型(type). 后三個(gè)取決于消息類型,是可選項(xiàng), 非必須。; 被用作是分隔符。即使并沒有包含上述可選項(xiàng), 但是在消息中仍然必須有三個(gè) ; 字符。

  •  COMMAND 是上面列表中的命令之一
  •  KEY 是一個(gè)可以用作數(shù)據(jù)庫 key 的 string (可選)
  • VALUE 是數(shù)據(jù)庫中的一個(gè) integer, list 或 string (可選) 

          list 可以被表示為一個(gè)用逗號分隔的一串 string, 比如說, “red, green, blue”

  •  VALUE TYPE 描述了 VALUE 應(yīng)該被解釋為什么類型 

           可能的類型值有:INT, STRING, LIST

Examples

2.Reponse Messages

一個(gè) 響應(yīng)消息 (Reponse Message) 包含了兩個(gè)部分, 通過 ; 進(jìn)行分隔。第一個(gè)部分總是 True|False , 它取決于所執(zhí)行的命令是否成功。 

第二個(gè)部分是命令消息 (command message), 當(dāng)出現(xiàn)錯(cuò)誤時(shí),便會(huì)顯示錯(cuò)誤信息。對于那些執(zhí)行成功的命令,如果我們不想要默認(rèn)的返回值(比如 PUT), 就會(huì)出現(xiàn)成功的信息。如果我們返回成功命令的值 (比如 GET), 那么第二個(gè)部分就會(huì)是自身值。

Examples

Show Me The Code!

我將會(huì)以塊狀摘要的形式來展示全部代碼。整個(gè)代碼不過 180 行,讀起來也不會(huì)花費(fèi)很長時(shí)間。

Set Up

下面是我們服務(wù)器所需的一些樣板代碼:

很容易看到, 上面的只是一個(gè)包的導(dǎo)入和一些數(shù)據(jù)的初始化。

Set up(Cont’d)

接下來我會(huì)跳過一些代碼, 以便能夠繼續(xù)展示上面準(zhǔn)備部分剩余的代碼。注意它涉及到了一些尚不存在的一些函數(shù), 不過沒關(guān)系, 我們會(huì)在后面涉及。在完整版(將會(huì)呈現(xiàn)在最后)中, 所有內(nèi)容都會(huì)被有序編排。這里是剩余的安裝代碼:

 

我們創(chuàng)建了 COMMAND_HANDLERS, 它常被稱為是一個(gè) 查找表 (look-up table) . COMMAND_HANDLERS 的工作是將命令與用于處理該命令的函數(shù)進(jìn)行關(guān)聯(lián)起來。比如說, 如果我們收到一個(gè) GET 命令, COMMAND_HANDLERS[command](key) 就等同于說 handle_get(key) . 記住,在 Python 中, 函數(shù)可以被認(rèn)為是一個(gè)值,并且可以像其他任何值一樣被存儲在一個(gè) dict 中。

在上面的代碼中, 雖然有些命令請求的參數(shù)相同,但是我仍決定分開處理每個(gè)命令。盡管可以簡單粗暴地強(qiáng)制所有的 handle_ 函數(shù)接受一個(gè) key 和一個(gè) value , 但是我希望這些處理函數(shù)條理能夠更加有條理, 更加容易測試,同時(shí)減少出現(xiàn)錯(cuò)誤的可能性。

注意 socket 相關(guān)的代碼已是十分極簡。雖然整個(gè)服務(wù)器基于 TCP/IP 通信, 但是并沒有太多底層的網(wǎng)絡(luò)交互代碼。

最后還需要注意的一小點(diǎn): DATA 字典, 因?yàn)檫@個(gè)點(diǎn)并不十分重要, 因而你很可能會(huì)遺漏它。DATA 就是實(shí)際用來存儲的 key-value pair, 正是它們實(shí)際構(gòu)成了我們的數(shù)據(jù)庫。

Command Parser

下面來看一些 命令解析器 (command parser) , 它負(fù)責(zé)解釋接收到的消息:

這里我們可以看到發(fā)生了類型轉(zhuǎn)換 (type conversion). 如果希望值是一個(gè) list, 我們可以通過對 string 調(diào)用 str.split(',') 來得到我們想要的值。對于int, 我們可以簡單地使用參數(shù)為 string 的 int() 即可。對于字符串與 str() 也是同樣的道理。

Command Handlers

下面是命令處理器 (command handler) 的代碼. 它們都十分直觀,易于理解。注意到雖然有很多的錯(cuò)誤檢查, 但是也并不是面面俱到, 十分龐雜。在你閱讀的過程中,如果發(fā)現(xiàn)有任何錯(cuò)誤請移步 這里 進(jìn)行討論.

有兩點(diǎn)需要注意: 多重賦值 (multiple assignment) 和代碼重用. 有些函數(shù)僅僅是為了更加有邏輯性而對已有函數(shù)的簡單包裝而已, 比如 handle_get 和handle_getlist . 由于我們有時(shí)僅僅是需要一個(gè)已有函數(shù)的返回值,而其他時(shí)候卻需要檢查該函數(shù)到底返回了什么內(nèi)容, 這時(shí)候就會(huì)使用 多重賦值 。

來看一下 handle_append . 如果我們嘗試調(diào)用 handle_get 但是 key 并不存在時(shí), 那么我們簡單地返回 handle_get 所返回的內(nèi)容。此外, 我們還希望能夠?qū)?handle_get 返回的 tuple 作為一個(gè)單獨(dú)的返回值進(jìn)行引用。那么當(dāng) key 不存在的時(shí)候, 我們就可以簡單地使用 return return_value .

如果它 確實(shí)存在 , 那么我們需要檢查該返回值。并且, 我們也希望能夠?qū)?handle_get 的返回值作為單獨(dú)的變量進(jìn)行引用。為了能夠處理上述兩種情況,同時(shí)考慮需要分開處理結(jié)果的情形,我們使用了多重賦值。如此一來, 就不必書寫多行代碼, 同時(shí)能夠保持代碼清晰。return_value = exists, list_value = handle_get(key) 能夠顯式地表明我們將要以至少兩種不同的方式引用 handle_get 的返回值。

How Is This a Database?

上面的程序顯然并非一個(gè) RDBMS, 但卻絕對稱得上是一個(gè) NoSQL 數(shù)據(jù)庫。它如此易于創(chuàng)建的原因是我們并沒有任何與 數(shù)據(jù) (data) 的實(shí)際交互。我們只是做了極簡的類型檢查,存儲用戶所發(fā)送的任何內(nèi)容。如果需要存儲更加結(jié)構(gòu)化的數(shù)據(jù), 我們可能需要針對數(shù)據(jù)庫創(chuàng)建一個(gè) schema 用于存儲和檢索數(shù)據(jù)。

既然 NoSQL 數(shù)據(jù)庫更容易寫, 更容易維護(hù),更容易實(shí)現(xiàn), 那么我們?yōu)槭裁床皇侵皇褂?MongoDB 就好了?當(dāng)然是有原因的, 還是那句話,有得必有失, 我們需要在 NoSQL 數(shù)據(jù)庫所提供的數(shù)據(jù)靈活性 (data flexibility) 基礎(chǔ)上權(quán)衡數(shù)據(jù)庫的可搜索性 (searchability).

Querying Data

假如我們上面的 NoSQL 數(shù)據(jù)庫來存儲早前的 Car 數(shù)據(jù)。那么我們可能會(huì)使用 VIN 作為 key, 使用一個(gè)列表作為每列的值, 也就是說,2134AFGER245267 = ['Lexus', 'RX350', 2013, Black] . 當(dāng)然了, 我們已經(jīng)丟掉了列表中每個(gè)索引的 涵義 (meaning) . 我們只需要知道在某個(gè)地方索引 1 存儲了汽車的 Model , 索引 2 存儲了 Year.

糟糕的事情來了, 當(dāng)我們想要執(zhí)行先前的查詢語句時(shí)會(huì)發(fā)生什么?找到 1994 年所有車的顏色將會(huì)變得噩夢一般。我們必須遍歷 DATA 中的 每一個(gè)值 來確認(rèn)這個(gè)值是否存儲了 car 數(shù)據(jù)亦或根本是其他不相關(guān)的數(shù)據(jù), 比如說檢查索引 2, 看索引 2 的值是否等于 1994,接著再繼續(xù)取索引 3 的值. 這比 table scan 還要糟糕,因?yàn)樗粌H要掃描每一行數(shù)據(jù),還需要應(yīng)用一些復(fù)雜的規(guī)則來回答查詢。

NoSQL 數(shù)據(jù)庫的作者當(dāng)然也意識到了這些問題,(鑒于查詢是一個(gè)非常有用的 feature) 他們也想出了一些方法來使得查詢變得不那么 “遙不可及”。一個(gè)方法是結(jié)構(gòu)化所使用的數(shù)據(jù),比如 JSON, 允許引用其他行來表示關(guān)系。同時(shí), 大部分 NoSQL 數(shù)據(jù)庫都有名字空間 (namespace) 的概念, 單一類型的數(shù)據(jù)可以被存儲在數(shù)據(jù)庫中該類型所獨(dú)有的 “section” 中,這使得查詢引擎能夠利用所要查詢數(shù)據(jù)的 “shape” 信息。

當(dāng)然了,盡管為了增強(qiáng)可查詢性已經(jīng)存在 (并且實(shí)現(xiàn)了)了一些更加復(fù)雜的方法, 但是在存儲更少量的 schema 與增強(qiáng)可查詢性之間做出妥協(xié)始終是一個(gè)不可逃避的問題。本例中我們的數(shù)據(jù)庫僅支持通過 key 進(jìn)行查詢。如果我們需要支持更加豐富的查詢, 那么事情就會(huì)變得復(fù)雜的多了。

Summary

至此, 希望 “NoSQL” 這個(gè)概念已然十分清晰。我們學(xué)習(xí)了一點(diǎn) SQL, 并且了解了 RDBMS 是如何工作的。我們看到了如何從一個(gè) RDBMS 中檢索數(shù)據(jù) (使用 SQL 查詢 (query)). 通過搭建了一個(gè)玩具級別的 NoSQL 數(shù)據(jù)庫, 了解了在可查詢性與簡潔性之間面臨的一些問題, 還討論了一些數(shù)據(jù)庫作者應(yīng)對這些問題時(shí)所采用的一些方法。

即便是簡單的 key-value 存儲, 關(guān)于數(shù)據(jù)庫的知識也是浩瀚無窮。雖然我們僅僅是探討了其中的星星點(diǎn)點(diǎn), 但是仍然希望你已經(jīng)了解了 NoSQL 到底指的是什么, 它是如何工作的, 什么時(shí)候用比較好。如果您想要分享一些不錯(cuò)的想法, 歡迎討論. 

 

責(zé)任編輯:龐桂玉 來源: 馬哥Linux運(yùn)維
相關(guān)推薦

2017-05-18 12:16:03

LinuxPythonNoSql

2020-10-31 22:01:40

NoSQL數(shù)據(jù)庫

2019-06-12 08:23:21

數(shù)據(jù)庫時(shí)間序列開源

2018-10-31 10:11:24

Python編程語言語音播放

2022-03-24 14:42:19

Python編程語言

2024-02-02 10:51:53

2021-09-28 09:25:05

NoSQL數(shù)據(jù)庫列式數(shù)據(jù)庫

2017-06-08 15:53:38

PythonWeb框架

2021-06-10 13:50:55

代碼開發(fā)數(shù)據(jù)庫

2011-10-09 09:38:03

OracleNoSQL

2013-02-27 10:23:55

NoSQL數(shù)據(jù)庫

2015-10-22 15:09:12

NoSQL數(shù)據(jù)庫應(yīng)用場景

2023-04-10 14:20:47

ChatGPTRESTAPI

2022-10-12 23:02:49

Calcite異構(gòu)數(shù)據(jù)框架

2024-03-28 09:00:00

NoSQL數(shù)據(jù)庫

2019-07-08 10:36:34

數(shù)據(jù)庫WebNoSQL

2019-03-20 15:59:11

NoSQLRedis數(shù)據(jù)庫

2011-07-19 09:08:50

JavaNoSQL

2010-04-01 09:45:38

NoSQL

2021-02-03 11:44:15

NoSQL關(guān)系數(shù)據(jù)庫
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號