方式(2)只用一段關(guān)聯(lián)語(yǔ)句查詢ResultSet rs = stmt.executeQuery("select amount from orders where status = “unpay” and username in ("select username from users where enable = 0") ");
這兩種方式如何取舍
但是問(wèn)題在于,如果是使用了子查詢的話,那么你需要一次進(jìn)程間通信,即 Java 給 MySQL 發(fā)送一次請(qǐng)求,然后 MySQL 查詢完成之后返回?cái)?shù)據(jù)。 但是如果是分開(kāi)兩次查詢的話,那么網(wǎng)絡(luò)通信的次數(shù)就變成了 1+(第一次結(jié)果集次),對(duì)于 MySQL 也好,Java 也好,他們的執(zhí)行速度都是很快的,慢的是他們之間的通信,所以使用子查詢的時(shí)候減少了他們之間通信的次數(shù),同時(shí)需要發(fā)送的東西也少了,所以子查詢會(huì)快一點(diǎn)。
我怎么覺(jué)得第二種不是1000+500 這么簡(jiǎn)單,select username from users where enable = 0數(shù)據(jù)庫(kù)需要跑1000次,select amount from orders where status =“unpay”這里也是1000次,復(fù)合這一句and username in也是要*500次吧,難道我思路錯(cuò)了
2018-11-27
從性能上看,關(guān)聯(lián)表查詢是為了應(yīng)對(duì)大數(shù)據(jù)查詢,減少查詢的基數(shù),靈活的配置主鍵等信息,提高查詢的效率;
從維護(hù)上看,關(guān)聯(lián)表查詢從表名上更容易明白功能的分級(jí),便于閱讀和維護(hù),并且模塊劃分越細(xì),后期越容易擴(kuò)展;
如果是程序開(kāi)發(fā)初期,使用人群較少,訪問(wèn)量數(shù)據(jù)量比較少,可以使用單表查詢;但是從長(zhǎng)遠(yuǎn)上看,防止訪問(wèn)量飆升,數(shù)據(jù)量也飆升導(dǎo)致性能變慢的情況發(fā)生,應(yīng)當(dāng)使用關(guān)聯(lián)表查詢。
2018-12-14
首先,建表
可以看到 我這里給 users 加的索引是 (username,enable) 而不是 (enable)。
然后當(dāng)我們用 explain 去分析你給的第一條 SQL 語(yǔ)句的時(shí)候,
就會(huì)發(fā)現(xiàn) users 表上面是使用了 `key_username_enable` 的,然后這個(gè)時(shí)候,根據(jù)索引的最左匹配原則,可以知道, mysql 把 username 這個(gè)條件下推了,所以這個(gè)時(shí)候,MySQL 對(duì)于上面的 SQL 語(yǔ)句的執(zhí)行應(yīng)該是類(lèi)似于以下方式
因此把它分成兩部分來(lái)理解應(yīng)該是
------------------------------------------------ 分割線 -------------------------------------------------------------------------------------------
好了, 其實(shí)上面的都是廢話來(lái)的。
如果你是分開(kāi)執(zhí)行上面那兩個(gè) SQL 語(yǔ)句,對(duì)于 MySQL 來(lái)說(shuō),他所需要的時(shí)間是差不多的,
因?yàn)槟闳绻亲硬樵?,其?shí)他也是先執(zhí)行外部的找出一條數(shù)據(jù),然后在進(jìn)去子查詢里面查詢的,和在 Java 里面分開(kāi)查詢是一樣的。
但是問(wèn)題在于,如果是使用了子查詢的話,那么你需要一次進(jìn)程間通信,即 Java 給 MySQL 發(fā)送一次請(qǐng)求,然后 MySQL 查詢完成之后返回?cái)?shù)據(jù)。 但是如果是分開(kāi)兩次查詢的話,那么網(wǎng)絡(luò)通信的次數(shù)就變成了 1+(第一次結(jié)果集次),對(duì)于 MySQL 也好,Java 也好,他們的執(zhí)行速度都是很快的,慢的是他們之間的通信,所以使用子查詢的時(shí)候減少了他們之間通信的次數(shù),同時(shí)需要發(fā)送的東西也少了,所以子查詢會(huì)快一點(diǎn)。
2018-12-14
sql運(yùn)行機(jī)制和java運(yùn)行機(jī)制不一樣,?sql語(yǔ)句只要配置合理,都是秒級(jí)的,甚至是毫秒級(jí)的,喜歡這個(gè)答案。只是看到有很多程序也存在使用第一種方法。不知道他們是怎么考慮的。既然mybatis可以那么方便的配置查詢語(yǔ)句,貌似很多業(yè)務(wù)層都可以直接寫(xiě)到SQL語(yǔ)句里了,程序只是負(fù)責(zé)傳參而已
2018-12-11
啊,你說(shuō)的對(duì),是我把sql語(yǔ)句看錯(cuò)了。
再分析一次,在不考慮緩存的情況下:
先執(zhí)行username in ("select username from users where enable = 0") 這是1000次,返回500的基數(shù)
500 * 1000 = 500000,確實(shí)次數(shù)已經(jīng)超過(guò)第一種很多了。
但是sql運(yùn)行機(jī)制和java運(yùn)行機(jī)制不一樣,如果要比速度,肯定sql要快,根據(jù)我的開(kāi)發(fā)經(jīng)驗(yàn),java很少寫(xiě)高量級(jí)的循環(huán)語(yǔ)句。sql語(yǔ)句只要配置合理,都是秒級(jí)的,甚至是毫秒級(jí)的。所以肯定是第二種最棒,要不我寫(xiě)了這么多年前端,也不會(huì)來(lái)研究數(shù)據(jù)了……
2018-12-10
我怎么覺(jué)得第二種不是1000+500 這么簡(jiǎn)單,select username from users where enable = 0數(shù)據(jù)庫(kù)需要跑1000次,select amount from orders where status =“unpay”這里也是1000次,復(fù)合這一句and username in也是要*500次吧,難道我思路錯(cuò)了
2018-12-07
我覺(jué)得肯定是關(guān)鍵表查詢效率要高:
假設(shè)username和amount都是1000條數(shù)據(jù),第一種查詢得到500條結(jié)果,第二種也是500條結(jié)果。
第一種方式:除去查詢效率,二維for循環(huán)效率極低,需要對(duì)比500*500=250000次,總次數(shù)是1000 +1000 + 250000.
第二種:相當(dāng)于先查詢username的500條組成一個(gè)新的表,然后從結(jié)果500條中查詢符合第二個(gè)條件的結(jié)果。總次數(shù)等于1000+500。
這效率一對(duì)比,就什么都不用說(shuō)了。