明明很多編程語言從對象數組中取數據比用SQL從表中取數據方便,為什麼資料庫還是使用SQL?
單純從模型上來說,感覺對象數組與資料庫中的表並沒有什麼區別。然後,資料庫里有 n 個表,那無非就是有 n 個對象數組。。。然後,用 SQL 從表中取數據,與用編程語言,從對象數組中取數據有區別嗎?
至於說「編程語言從對象數組中取數據比用SQL從表中取數據方便」,我覺得是這樣的。
當然,我的確了解的 SQL 也不多,就會用些普通的 1992 版的 SQL。。。(好像是 1992 吧)。。。
舉個例子:有張表 post { id, content, author_id, created_at } 。。。然後我們有 10 個 author_id ,要求獲得這 10 個 author 各自的最新發布(created_at desc) 的 5 篇 post 。。。不足 5 篇的自然是有幾篇拿幾篇唄。。。就這個例子,用我所知道的 sql 1992 似乎無法一次性得到。。。但是如果是編程語言,拿 js 舉例,那簡直容易到爆:author_ids.map(author_id =&> posts.filter(post =&> post.author_id === author_id).sort((p1, p2) =&> p2.created_at - p1.created_at).slice(0,5))
所以,如題,為什麼明明很多編程語言從對象數組中取數據比用SQL從表中取數據方便,但資料庫還是使用SQL?
-------------分割線-------------
添加一點,避免有人答的不是我想問的:我想問的是關係資料庫 RDBMS。。。然後,在我的眼裡,資料庫只需要做到兩點,就可以認為是關係型資料庫:schema 和 事務。
然後,我並不在乎資料庫與項目開發語言環境的結合,也就是說 ORM 不 ORM 什麼的,我無所謂。。。我在乎的是 SQL 本身用起來感覺就沒有通用編程語言方便。。。
再然後,下面「唐生」的回答,他關閉了評論,我這裡還是說下:首先謝謝你的回答。我的代碼說不能讀,呃,最多就是沒有認真換行而已吧,這都小事。。。然後你的方法需要資料庫支持 row_number ,可是世界第一流行的 MySQL 都不支持(補充是 5.X 不支持,現在新版的是支持一些窗口函數的,但老實說,還是覺得不好用),這還不能說明問題嗎?然而我的方法里,幾乎沒有哪個通用編程語言不支持的吧,就算不支持,其實也是很容易擴展出來的吧(JAVA 1.6 不支持閉包,那就用匿名類唄)。。。
--------------分割線2-------------
下面有很多說 LINQ 的,其實我還可以告訴你們有 scala 的 slick,玩起來可能比 LINQ 更爽,但就算那樣,那也沒有直接使用原生語言爽。。。而且,這些東西的誕生,不正證明了 SQL 用起來很不爽嗎。。。
下面還有說內存里不可能放這麼大的一個數組的。。。內存里當然不可能放上億上十億條記錄的數組,但是我這只是類比啊,類比啊,類比啊。。。難道就一定要是數組才能使用通用編程語言才行嗎?`post.filter(p =&> p.author_id === author_id)` 這裡面的 `post` 就一定要是數組嗎?就不能是一個 `cretiria(雖然這東西是啥我也不知道)`,是一個游標啊之類的嗎?語言只是形式,實現當然可以採用更好的實現。。。
然後還有說 JS 的。。。呃,我這裡用 JS 只是因為我 JS 最熟,但我從沒說過資料庫就應該支持 JS,它可以是支持別的任意一種通用編程語言,甚至新開發一門語言。為了運行速度,最好是編譯型的強類型編程語言。。。然後資料庫客戶端把該語言的代碼和要傳的參數發給資料庫,資料庫編譯一次後緩存起來,這有什麼問題嗎?。。。。當然,這與我要問的問題無關。。。。我的問題只有一個:
SQL 用起來很不爽,相信有很多人都有這種感覺,那麼,為什麼那些關係資料庫仍然不找一門語言替代 SQL,畢竟,現成的,比 SQL 爽的語言遍地都是。。。就算資料庫開發商覺得這些語言還不夠好,那新開發一門語言也完全可以啊。。。
-------------分割線3---------------
下面還有一大群人說 NoSQL 的。。。可是現實里哪有什麼 NoSQL。。。都是 NoRrelationDBMS。。。此類資料庫被開發出來的目的都是因為關係資料庫不好做橫向擴展,查詢、插入的速度都不夠快。。。於是他們放棄了事務,放棄了Schema,於是出來個叫 NoSQL 的東西。。。可是關係資料庫不好做橫向擴展跟 SQL 有什麼關係,明明是 關係資料庫 這個「關係」二字導致的。。。一群人,名字都取錯了,明明應該叫 NoRrelationDBMS。。。跟我想要的「不使用 SQL 的關係資料庫」根本不是同一個東西。。。
還是上面那句話,我的問題只有一個:SQL 用起來很不爽。。。你們如果覺得 SQL 用起來很爽,那就來反駁我唄。想出一個查詢需求,分別用 SQL 和 一門通用編程語言來實現(通用編程語言當然是各種基礎設施已經做好了的,例如 map filter 函數),看看什麼時候 SQL 能比通用編程語言要簡單的呢。。。。。。
感謝「羅宸」的答案,知呼也沒有個採取答案的說法,只能點個贊和在問題里提下表示感謝。。。其他許多答案好像都沒看出我到底想要什麼。。。「在下送飯」的答案里倒是提到了「Object Oriented Database」,但其實跟我想要的還是有些許區別的。。。另外也有一些答案說出了原因,例如「通用編程語言不好優化」,可是沒給出令人說服的證據:SQL到底進行了什麼優化,而通用編程語言到底又是哪裡不好優化(我覺得使用通用編程語言,只要 API 保守一點,優化根本不是問題)。。。
無論如何,感謝各位的回答,不過看樣子只能繼續抱怨著 SQL 的不好用,繼續用著 SQL 了。。。
這個問題被瀏覽的挺多的啊,能做個廣告不?我的另一個問題,雖然與 SQL 無關。。。我這只是一個想法,探討下。自然界中有沒有天生的電子貨幣?,幫忙挽下尊?
謝邀。
首先SQL只是關係資料庫的一個查詢前端,並不是關係資料庫必要的一部分,只是按照國際慣例,大家都實現了這個介面而已。你也可以搞datalog,Tutorial D或者其他小眾的DSL。其他另如RethinkDB、CouchDB或者MongoDB,當然也是用JS在做Query Language,畢竟在這種schemaless的場景下,SQL就不太適合了。
另外,大部分關係資料庫實現都會對SQL進行一次編譯轉成特定的語法樹之後進行查詢計劃(Query plan),這個過程會利用索引等信息進行優化。而相對於每一個去連接/調用資料庫的應用來看,這些所有的操作就被SQL完美的隱藏了起來,無論針對哪一種編程語言/平台,都會有一套統一的實現。這樣也就省去了每個主流的編程語言都需要再去設計一套介面的成本。
第三點就是,SQL面向的不只是程序員,還有各種系統分析師、數據分析師甚至是某些高管們,所以只是一個「查詢語言(Query Language)」,而不是一個通用編程語言(General Purpose Programming Language)。所以其更多的是拿來描述數據和關係,特別是當需要組合/連接多個關係的時候,通用編程語言的表示方式可能會不如SQL看上去直接。不然為啥微軟還費盡心機地在C#裡面造一套Linq幹嘛。
下面有很多說 LINQ 的,其實我還可以告訴你們有 scala 的 slick,玩起來可能比 LINQ 更爽,但就算那樣,那也沒有直接使用原生語言爽。。。而且,這些東西的誕生,不正證明了 SQL 用起來很不爽嗎。。。
題主理解錯誤,Linq 並不是指IQueryable轉換為SQL語句,而是通過仿SQL的Linq語法轉換為對象方法鏈。跟slick不是同一類東西。參見:Language Integrated Query (LINQ)
作為一個SQL語法的戰五渣,個人還是覺得Linq語法比使用方法鏈更容易看。
很多人已經提過NoSQL,可能題主也沒太了解?NoSQL就不是主要用SQL語法。然而代價就是它們的數據結構要做改動,往往也不是題主所說的數組。
然而NoSQL也沒蹦多遠,參見:為什麼說SQL正在擊敗NoSQL,這對數據的未來意味著什麼?
拋開SQL歷史悠久,已經形成生態不說,自古有說法:「撼岳家軍易,撼C++難。」可以類比。
作為一門資料庫的DSL,相對一般語言來說,優點當然是:語法噪音少。
對資料庫引擎來說,限制用戶的自由度,更有利於優化。
對於用戶來說,告訴對方要什麼,而不是怎麼做,其實也是編程的一個趨勢。恰恰也是SQL和HTML製造了一個DSL成功的典範。題主可以去搜搜為什麼用DSL。當然也有的人不喜歡的,譬如王垠,當然他也只是說不要創建新的DSL,有一定道理,但是他也不敢噴SQL啊。
說到最後,這就是個趣味的問題,更多人喜歡DSL。
這其實是個很大的話題,先拋結論再詳述:跟歷史原因無關,也跟數據量無關,而跟關係數據模型的本質有關,SQL,直到現在(敲黑板),也是最適合&<手動加粗&>關係數據模型&手動加粗&>的查詢語言。 (同理,SPARQL就比通用編程語言適合triple-store model,Cyphe就更適合圖狀數據模型)
----------------------------------------------------------------------
很有意思,看題主和眾答主論戰了起來,且貌似還沒有看到滿意的答案,不禁想從一個系統設計原則的角度,認真回答一下。
這其實是一個語言表達力的選擇問題。最簡單的,沒有CTE和Windowing支持的SQL,作為一門非圖靈完備語言(有了CTE和Windowing支持,SQL可以組成一個Cyclic Tag System[1],而且Cyclic Tag System是已證圖靈完備的[2]),是被任何通用編程語言在表達力/能力上完爆的。所以你用JS表達一個問題的解法很爽,而用SQL非常捉急,那是非常合理正常的。因為JS的表達能力完爆SQL10條街。
然而,SQL的強就在於它表達力的弱。
「Extremely flexible sometimes equals to not flexible at all, while the least of power is extremely powerful.」 ---- by 阿萊克西斯
根據Rule of least power,我們要選擇適合目標問題的多個計算機語言中,最弱的那個來解決問題。Rule of least expressiveness[4]page-323也提到了這點。請謹記這條法則,它可以解釋很多技術選擇/發展的原因。關於Rule of least power還有一個無關本題但很有意思的推論可以在本文最後觀看。
詳細的論述請看鏈接,我簡單解釋一下。
越弱的語言,可以表達出的不同的possibility越少,比如+-*/形成的運算系統只可能是做數學運算,而不會刪除你的數據文件,不會數組越界。
同時,SQL作為關係數據模型的查詢語言,它的表達力著重在表達關係,就是多數據集作join。對於你的單表例子來說,是圖模型,關係模型,還是文檔模型,差距並不大。這時候通用編程語言在某些場景不僅比SQL表達力強甚至比SQL更簡潔都是可能的, 因為單表操作跟list操作差不多。但是在多數據集作join的時候,真正體現關係數據模型的關係二字的時候,情況就大不相同了。
比如一個簡單的SQL join
select a.product, b.price
from Produce_Table a, Price_Table b
where a.product_id = b.product_id;
如果用通用編程語言來寫就比較捉急(用大家都看得懂的java -_-)
products.stream()
.flatMap(x -&> prices.stream()
.filter(y -&> y.getProductId().equals(x.getProductId()) )
.map(y -&> Pair.pair(x.getName(), y.getPrice())) )
.collect(Collectors.toList())
SQL更清晰的表達了想做什麼,更符合separate concern的原則,不同的clause合理的安排在了select,join on, where 這些段落里,而編程語言的表達則很難分清那裡在做什麼。
所以說SQL在表達關係上(做join),很適合,很簡單,很符合人類的認知習慣,這只是2個表的join,改成5個表SQL也不會複雜很多,但是用code實現就難讀多了。且不說5個表,把inner join改成full join, SQL只需要加一個關鍵字,用code你可以試試如何實現。(寫完了再想一下4表fulljoin5表fulljoin怎麼支持,跟SQL實現對比。然後怎麼靈活的調整突然有一個join想要變成left/right join了怎麼改。如果你是一個善於抽象的coder,那麼你必然會抽象出一個控制層,通過調參來實現靈活性,到時候你會發現你的控制層等價於某種SQL方言)
這裡多說一點Spark的Dataframe模仿SQL的函數api(這裡用scala ),比如
val filteredProduct = product.filter("type === "Book").as("pr)
val join = filteredProduct.join(prices).where($"pr.productId" === $"prices.productId")
join.select($"pr.name", $"prices.price").limit(5).show
這並不是通用編程語言的函數,SparkSQL在實現這些filter,join,where,select函數的時候,內部生成了和SQL一樣的語法樹。這和ORM的函數API的trick類似,ORM甚至直接ping 資料庫的時候,傳過去的是根據函數API翻譯好的SQL,所以你可以把這些api看作SQL而不是通用編程語言的函數。
比較3個版本, SQL最簡單達意。
這意味著,從理解性來講,SQL很強,因為它的表達力很弱,很簡單。
這不僅僅是對於我們人來說,對於語言的解釋器也是一樣。比如在where里,你只能表達filter,在join on里只能表達join條件。而在stream的filter函數里,你可以傳入任何返回boolean的函數。而這無限的可能讓解釋器束手無策。這無限的可能讓你不能對不會發生什麼有任何假設,而對可能會發生什麼有無限需要去支持的假設。這裡邊的差距就大了。
SQL的解釋器,只需要理解支持很少possibility,由於SQL本身很弱,限制很多,所以SQL的解釋器可以做的很自由,很強;當它看到一個SQL,它知道作為writer,意圖只可能是表達join兩個表,那麼它可以用任何演算法(nest loop, Hashjoin, sortmerge)來實現你的目的。而通用編程語言的compiler看到這段code,看到map,flatmap, filter,它不能過多的假設你想做什麼,因為map,flatmap,filter作為通用函數,太強了,有太多的possibility需要去假設,你甚至可以在map()里去連接資料庫,所以compiler無法從整體上理解你的意圖,然後隨意選擇演算法來實現join兩個數據集然後給出最終答案,而只能根據你的指令來運算。
表達力增加的可能性, 限制了理解力,增加了讀者(人或機器)的複雜度,限制了讀者能做什麼。
最後,關於為什麼我們要用SQL,答案就一目了然了:
1. SQL在表達關係模型的時候是自然簡單的,很容易表達關係模型的join,複雜的join,是SQL相對通用編程語言的優勢,這點從通用編程模型實現多表full join,自由變化join類型非常麻煩複雜就能看出來
2. 對於關係數據模型來說,SQL是能夠支持關係模型的所有計算機語言里,表達力最弱的語言。通過這種簡單, 表達力弱的語言抽象,語言實現者有更多的餘地來優化內部實現。這點,從任何支持SQL的資料庫,都有通用編程語言望塵莫及的optimizer就可以看出來了。
另外, 在同一個Spark平台上,Dataframe API(模擬SQL)的性能爆掉RDD API(支持通用編程語言函數)的性能10條街也能看出來。。。。
圖出自[5]
PS:NoSQL不是Not use SQL或者No relation SQL,而是Not only SQL.
PSS: 你想當程序藝術家嘛? 什麼是程序藝術家(霧
PSSS:還有一個法則叫做The Principle of Least Power 基本和Rule of Least Power一樣, 它有一個有意思的推論叫做:
Atwood"s Law: any application that can be written in JavaScript, will eventually be written in JavaScript.
那麼根據本文可知,Atwood錯了,SQL比JS還弱,所以根據他的推論本源的Rule of least power,同時能用SQL和JS構造的app,會最終由SQL構造而不是JS(笑)。(本人並不喜歡SQL,所以只是推論調侃,並不代表我真的認為能用SQL的就應該用SQL)
[1]High Performance SQL with PostgreSQL Presentation
[2]Cyclic Tag System
[3]Rule of least power
[4]Concepts, Techniques, and Models of Computer Programming
[5]Best Practices for Scaling and Optimizing Apache Spark: Holden Karau, Rachel Warren: 9781491943205: Amazon.com: Books
你說的那個東西叫LINQ
看了下題主的問題,題主吐槽的應該是關係型資料庫為什麼要使用SQL作為查詢語句,而不是當初為什麼是關係型資料庫勝出了。 如果理解得當的話,那原因也很簡單。關係資料庫的原理是關係代數,即Projection/Select/Cross Product等等關係運算符, 這一塊正好對應於sql語言的各個語法。 很自然的對應。 如果讓你來設計第一個資料庫,你到看Ted Codd的論文,你就很容易設計成類似於SQL這樣的申明式語法。這是為什麼會設計成類似於SQL的原因。
再說為什麼不會設計成題主所說的語言(假設題主還是使用關係型資料庫作為數據引擎)。 題主的語言實際上就是內含了資料庫訪問數據的邏輯和方法。 如果,題主的寫法是比查詢優化器得到的查詢方法更優的方法,那完全沒問題。 但是,這時你要想得到較優的寫法,你就必須得知數據底層的存儲結構、數據的分布, 去計算各種join的優劣。 這在軟體系統設計上是違反抽象原則的。 所以大概率下你的寫法是劣與查詢優化器的。 如果此時,你還需要將你的語言轉化為關係運算元再到查詢優化器優化, 那如果是我設計系統,我又何必多此一舉,直接提供給你和關係運算元一一對應的SQL就好了啊,然後由你框架提供ORM轉換到SQL語句就好了唄。多簡潔。
先說題主的看法可能有問題的地方吧
首先,關係資料庫的表其實不應該跟數組做類比,因為本來就不是數組,說是鏈表更恰當,數組可以直接根據下標取第k個元素,而資料庫表一般來說不直接提供這個功能,就算實現也是有其他做法
其次,題主舉的例子,就是從多個表拿post那個,這是「業務需求」,而sql作為資料庫介面,提供的很多是基礎功能,就是讓你用這些基礎功能去拼湊的,業務需求都交給sql是不現實的(不過現在的sql語法越來越豐富,配合存儲過程什麼的也能做到,但維護性。。。反正我不喜歡)
再次,你用自己寫程序去代替sql,理論上是可以的,但是這基本相當於你自己實現一個資料庫了,比如數據的索引什麼的,當然如果你的數據很少,不用考慮性能,自己在內存暴力擼也可以,但你得保證自己寫的代碼比sql還好維護,沒什麼故障才行(如果考慮團隊合作,這個很難,就算你自己水平好,不代表別人也有這個水平,而大量用sql雖然笨重了點,但是維護方便)
最後,資料庫也不一定就是sql,也有很多nosql資料庫,你可以找一下,可能還更方便
再說說題主看法的可取之處
第一,對於很多小的需求來說,sql和關係資料庫是有點笨重了,不然也不會有那麼多後起的資料庫,不過這也是使用選擇的問題,根據你們的開發需求來選
第二,sql用起來不爽,雖然是一個主觀的因人而異,但也是現實存在的,所以可以封裝或找替代品,但是也不能說,因為你只熟悉或者很喜歡js,就一定要用js的方式去存取,如果每個人都這樣做,項目和團隊合作就難搞了
題主的問題提得非常好,這年頭能有意識地把抽象手段和實現方式分開來討論的程序員其實不多,所以很多答主拿內存什麼的說事也很正常,但很多人這麼說不代表他們就是對的。
事實上,題主思考的是一個編程界面的設計問題,我來重新表述一下問題,就是:為什麼資料庫訪問界面要設計成SQL這種形式,而不是以函數調用這種更直觀和易於組合的形式提供。
其實這樣的資料庫是有的,最家喻戶曉的例子: Spark就是通過Scala語法,以FP style提供的數據訪問界面, 但這也並沒有妨礙別人處理大數據 (所以可以知道拿內存來嘲笑題主的觀點是站不住腳的), 不僅不妨礙, 並且在做並行優化上還有優勢. 下面這個是Spark官網上的例子:
text_file = spark.textFile("hdfs://...")
text_file.flatMap(lambda line: line.split())
.map(lambda word: (word, 1))
.reduceByKey(lambda a, b: a+b)
當然,目前市場上還是提供SQL界面的資料庫產品居多 , 但這並不能說明題主的疑問就是毫無道理的 , 我只能告訴題主:
- 這個現象一部分是歷史原因導致的. SQL作為一個成熟的數據訪問界面, 已經成為了某種事實標準, 那麼新的產品如果不遵守既有的事實標準, 那麼在推廣和應用的過程中就會受到阻力, 這是無法迴避的問題, 所以很多NoSQL的資料庫產品為了被市場接受, 也常常會推出SQL界面支持.
- 大家不容易就可讀性達成一致意見. 可讀性和直觀性的標準是比較主觀的, 確實很難一概而論, 可能你覺得A方式比較直觀可讀, 而你的同事覺得B方式比較直觀可讀, 這是常常發生的事情, 而SQL之所以能夠在過去的時間裡成為事實標準, 一定程度上還是能說明, 它的可讀性是能夠被數量不小的一批人接受的.
另外, 如果題主要問的是 "為什麼當年要把SQL設計成這麼難用的DSL, 而不是設計成FP style的EDSL?" 的話, 我只能從實現層面做一些猜測 (注意, 以下是個人猜測, 沒有證據支持, 請謹慎參考):
- 在當時類型系統的應用程度上來講, 設計一個報錯信息友好的DSL, 比設計一個報錯信息友好的EDSL更容易.
- 就當時的資料庫優化技術來說, SQL這樣的DSL設計可能是相較而言更易於優化的.
所以我們通常用資料庫來儲存那些大到數組裝不下的數據。
其中一個原因是SQL查詢把具體的語言和資料庫之間給解耦了。
否則的話,對應每個語言,資料庫都要開發一個對應驅動,而這個東西要比SQL底層多了,因為你要和資料庫內部的數據結構和機制打交道,還要自己優化。你看到的語言工具,很多都是把這樣的東西轉換成SQL進行操作的。
當然你也可以一次性從數據載入所有數據,然後完全在內存中用語言自帶的工具查詢,前提是你要能完全載入,並且根據你的查詢設計出合適的數據結構(索引優化),然而對於一個稍微複雜一點的圖的搜索,通用語言的演算法可能就變成一個NP問題了(我做過這樣的項目,在一個國家鐵路網資料庫裡面進行最短路徑搜索,數據量並不大,但是數據複雜度很高,結點之間的關聯度很大,而且這個圖還是分層的,只能預先用SQL進行預搜索)
而且你看到的這些語言特性,都是最近十年才進入主流的,原先只存在於FP裡面,之前你要用主流語言,在沒有閉包的情況下做這些東西,你只能用一個個for,既不方便又容易出錯
SQL is the only widely used 4GL in commercial use today. Artificial intelligence languages are also classified as 4GL.
Language - Generation (1GL, 2GL, 3GL, 4GL)
如果你的數據就那麼一點,內存都能放下,那好好用數據結構也不是不行。
反正C#有Linq
你這樣編程是很難得到資料庫的性能的。
數據量一大你代碼就會處處爆炸其次你也沒有考慮線程安全也沒有考慮臟讀也沒有緩存換句話說你考慮了一個非常狹小的特定場景,然後得出我已經寫代碼比sql快而且方便的結論代價是喪失了通用性你需要好好理解每個資料庫的特定的功能。然後在特定情況會選用特定資料庫。數據是存儲在db裡面的,你想要用你說的「對象數組」,那麼請問「對象數組」從哪裡來」?
SQL是操作關係型數據的標準編程語言,包括DQL,DML,DCL,DDL等等部分。不單單只有你說的查詢部分,其次數據是有關係的,是有其他的需求的,不是單單你定義一個數組能搞定的事情。
至於你說的這個語法,這只是某一些語言操作集數據的私有方式而已,比如js的lodash庫,c#的LINQ。不,是 SQL 方便:
select id from (
select id,
row_number() over (partition by author_id order by created_at desc)
from posts
) t0
where row_number &<= 5;
多清晰啊。你那 js 能讀?
當然這個要引擎支持 row_number 這種窗口函數,像 MySQL 5.x 就是沒有的。
SQL 是關係代數的 DSL,描述的是「結果」而不是「過程」,像你的 js 裡面的過濾、排序、取子集等等,都不用使用者自己寫,資料庫自己會生成執行計劃,只需要你用 SQL 描述一下想用什麼數據就行了。
題主自己主觀了。
我也不喜歡SQL,一直盼望著有一種成熟的面向對象的資料庫呢。
然而,這話是不對的:
明明很多編程語言從對象數組中取數據比用SQL從表中取數據方便
人家DBA還覺得「明明是SQL比很多編程語言更方便」呢!
你這就相當於中國人說英語難學,或者外國人說中文難學一樣,太過於主觀了。
你覺得SQL不方便,只是因為你對SQL不熟而已。
其實,更有趣的問題應該是:
為什麼不能用同一種語言完成對從UI到資料庫的全部操作呢?
比如,我們前台用javascript,後台用C#(或JAVA等),資料庫用SQL,確實麻煩。所以node.js出來的時候前端一片歡呼雀躍,然並卵,很快大家就發現不是那麼一回事。
個人覺得,這涉及到分工和競爭。
首先是分工,專業的人做專業的事。搞資料庫的,就專門折騰資料庫;搞UI的,就一門心思的弄UI……長期的社會實踐已經證明,這種操作反而更有效率。
其次是競爭,現在C#的語法能進化得這麼溜,主要還是有JAVA之類的競爭威脅。如果一家獨大的話,反正我覺得windows是一年比一年難用。
所以很多編程語言都有 ORM 啊……
所以有 NoSQL 資料庫比如 MongoDB 啊……
為什麼有了美顏相機和美圖秀秀大家還需要那麼複雜又麻煩的PS呢?因為美顏相機能做的事情PS都能做,反過來卻不行。
我朝高速最高限速120,隨便10萬的買菜車都能開到這個速度,你買輛極速300的法拉利回來也只能按這個限速開,那說明法拉利和買菜車沒差別甚至因為買菜車到處都能修保養還便宜所以更好?
不嘲諷地說,等你深入使用了資料庫而不是僅僅簡單地從表裡讀寫數據之後再來討論這個話題吧。
邪性,除了專門做資料庫研究的人已經很少有人會提到完備級SQL92,我很好奇你是從什麼渠道了解到這個知識點的作為交換,如果你解釋了我的疑問,倒是可以給你講講資料庫實現層次的架構原理。
雖然有點沒有看懂樓主在問啥...強答
SQL是一種Declarative programming,簡單的說這是一種描述what的語言,你只需要告訴資料庫需要什麼...
而general propose的編程語言通常是多範式的,比如樓主寫的JavaScript就很函數式...多數編程範式是關於how的,也就是說,你需要告訴計算機做什麼...這一點在命令式編程編程里很明顯,我們需要顯性的告訴計算機一個變數要怎麼變化,或者對於函數式來說,一個函數內部具有什麼樣的定義。
以排序舉例,SQL desc就完了(或者複雜一點用order by指定排序依據),用lambda的話仍然需要指定一個匿名比較函數,which接受列表中的兩個變數返回一個bool...(顯然後者表達能力更強,但是也相對複雜,畢竟SQL只是一個DSL)
其實函數式確實也很適合處理數據(也許比命令式編程更適合),所以最重要原因大概是歷史原因了。簡而言之,因為函數式在中古時期不流行啊,沒形成通用標準啊。
SELECT
f.*,ff.desciption,ff.icon,ff.moderators,ft.*
FROM
forum f
LEFT JOIN
forum_field ff
ON
ff.fid =f.fid
LEFT JOIN
forum_thread ft
ON
f.fid = ft.fid
WHERE
f.type IN("forum","sub")
AND
f.show = 1
AND
ff.password = ""
AND
ft.display IN(0,1,2,3)
GROUP BY
f.fid
ORDER BY
f.order DESC ,
ft.dateline DESC
LIMIT
10,20;
代碼實現這個語句,代碼量是多少?
有張表 post { id, content, author_id, created_at } 。。。然後我們有 10 個 author_id ,要求獲得這 10 個 author 各自的最新發布(created_at desc) 的 5 篇 post 。。。不足 5 篇的自然是有幾篇拿幾篇唄。。。
不得不說,題主給的問題,是很取巧的
因為 關係型資料庫,不支持 多緯數組 ……
對SQL來說,數據是單層的……
這也就是 為什麼 題主給出的問題,看上去用SQL解決很麻煩
——因為,這本來就是不應該SQL去解決的問題
author_ids.map(
author_id =&>
posts.filter(
(post)=&>{
return post.author_id === author_id;
}
).sort(
(p1, p2) =&> {
return p2.created_at - p1.created_at
}
).slice(0,5)
)
題主給的代碼,應該是可以理解成這樣吧?
如果是這樣,應該也不能認為是 一次性得到 才正常。
因為 內嵌了函數啊…… 如果內嵌函數也算一次的話……即便不用內置事務
(SELECT * FROM forum_thread b where uid = 1 ORDER BY time DESC LIMIT 5)
UNION
(SELECT * FROM forum_thread b where uid = 2 ORDER BY time DESC LIMIT 5)
也可以啊…… 本質上 和 題主的實現方式並沒有什麼區別:
posts.filter() 等價於 SELECT * FROM forum_thread where uid = 1
sort() 等價於 ORDER BY time DESCslice(0,5) 等價於 LIMIT 5
題主的代碼也可以變為
author_ids.map(
(uid)=&>{
let sql = "SELECT * FROM forum_thread b where uid = "+uid+" ORDER BY time DESC LIMIT 5"
return DB.result_array(sql)
}
)
而在一定數據量的情況下,我是不相信 JS的函數會比SQL更快 的……
理由的話……因為 SQL有索引啊,有底層支持啊……
————————————————————————————————————
SQL的語句 只是一種規範,
就像 我們還可以把這種規範,封裝成 PDO 或者 LINQ 之類……
而SQL的底層實現,其實不也是 C啊 之類的語言嗎?
而SQL所做的,
不也就是 如何快速的從 文件系統和一個大字元串里 篩選出對應的內容嗎?
其實 和題主你所做的所想的 並沒有什麼不同
只不過,已經有前人把這些都封裝成了 XSQL 服務而已……
推薦閱讀:
※為什麼Python程序不怎麼佔用CPU資源?
※假如DNA是一種編程語言,那麼誰能保證人類對DNA的修改沒有bug?
※CPU空操作的原理是什麼?
※如何評價 VBA 語言?