【一個idea】YesSql,一種在經典nosql數據庫redis上實現SQL引擎的方案(我就要開歷史的倒車)


公眾號鏈接

最高級的紅酒,一定要摻上雪碧才好喝。
基於這樣的品味,我設計出了一套在經典nosql數據庫redis上實現SQL引擎的方法。既然redis號稱nosql,而我偏要把SQL加到redis上,於是這個技術方案取名為【YesSql】。

產品商標

1.在redis上實現SQL查詢的技術基礎

  • redis上可以執行lua。整個SQL引擎就是在lua上解析SQL語句,執行,並返回結果。
  • lua有很好的正則表達式引擎,因此解析SQL語法變得簡單。
  • redis提供map, zset這樣的數據結構,很容易實現列存儲
  • 關系數據庫不也就是索引+遍歷,核心邏輯完全能用lua來實現。

2.實現細節

2.1 create table

  • 假定我只支持number和string兩種數據結構
  • 把整個按行組織的表看成由N個字段組成的列存儲
    • 也就是說,字段的組織是: table_column -> map 或 zset
    • 用一個 table_rowid -> int 來產生一個rowid
    • map或者zset中的key使用rowid:
${table}_rowid -> int_value
${table}_${column1} -> map
  ${rowid1} -> column1 data of row 1
  ${rowid2} -> column1 data of row 2
${table}_${column2} -> map
  ${rowid1} -> column2 data of row 1
  ${rowid2} -> column2 data of row 2
  • 可以有唯一索引:
${table}_unique_index_1 -> map
    ${unique_key_1} -> rowid1
    ${unique_key_2} -> rowid
  • 可以有數值類型的排序索引:
${table}_number_index_1 -> zset
    $rowid1 -> number1
    $rowid2 -> number2
  • 所以:create table就是建立上面的KEY結構
  • 建表的語法大致如下:
create table my_first_redis_table_1(
    column1 number,
    column2 string,
    column2 number
    unique index column2,
    number_index column3
)

2.2 insert

  • 插入時先要使用redis的INC指令得到一個新的rowid
  • 插入其實就是在${table}_${column}字段的下面增加二級KEY

2.3 update

  • update可以指定rowid或者唯一索引中的字段
  • 如果where條件比較復雜,則只能遍歷字段,並最終取多個rowid集合的交集
  • set中的字段,先找到rowid,然后根據rowid更新就好了

2.3 delete

  • where條件中的搜索如同上面
  • 刪除行就是逐個刪除每個column key下面的rowid對應的二級KEY

2.4 select

這部分相對復雜,划分為不同的場景:

2.4.1 from部分

解析出表名是第一步的,然后就確定了KEY的前綴。

2.4.2 where條件

上面講update和delete的where部分一筆帶過了,具體有這樣的一些場景:

  • 使用rowid=xxx或者rowid in ()的方式,比較簡單
  • 使用unique_key=xxx或者unique_key in ()的方式,也比較簡單,先通過唯一索引得到rowid,然后再根據rowid查詢
  • 使用number_index的范圍查詢的情況,先使用ZRANGEBYSCORE找到多個rowid,然后再查詢
  • 使用and/or/in及其其他字段上的表達式,無非也就是層層加過濾,知道最終確定rowid的集合

2.4.3 select部分

  • 每選擇一個列,就意味着要輸出這個列的值給查詢方
  • 字段上的表達式,也比較容易實現

2.4.4 group by部分

  • 可以建立一個所有group by中字段名組合起來的臨時KEY作為二級KEY的map
例如:
select column1, column2, count(1), sum(column3)
from table
group by column1, column2

可以建立這樣的KEY結構:
temp_group_by_1 -> map
    ${column1_value}_${column2_value} -> rowid
temp_group_by_1_stat1 -> map
    $rowid1 -> count_value
temp_group_by_1_stat2 -> map
    $rowid1 -> sum_value

2.4.5 having部分

  • having部分,也就是在上一步匯總好的基礎上,對rowid指向的值做過濾。
  • 還有一個優化點:如果沒有having字句,匯總采用map結構;有having字句,采用zset結構,直接根據范圍做過濾

2.4.6 join部分

不再敘述,猜測不會有那么無聊的人真的希望用上這么一套SQL引擎。

3.最后

  • 這是一個惡意的玩笑
  • 某種程度上可以作為一種思維訓練,讓我們知道SQL引擎可能是怎么去運行的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM