佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 5399|回复: 9

MSSQL query 加速ing

[复制链接]
发表于 14-9-2015 02:05 PM | 显示全部楼层 |阅读模式
题目1:我有3个query:
SELECT A.* FROM TABLE A, TABLE B, TABLE C
WHERE A.ID = B.ID AND B.SUBID = C.SUBID AND A.NAME = XXXX AND C.ADDRESS = YYYY

OR

SELECT A.* FROM TABLE A
INNER JOIN TABLE B ON A.ID = B.ID
INNER JOIN TABLE C ON B.SUBID = C.SUBID
WHERE A.NAME = XXXX AND C.ADDRESS = YYYY

OR

SELECT A.* FROM TABLE A
INNER JOIN TABLE B ON A.ID = B.ID AND A.NAME = XXXX
INNER JOIN TABLE C ON B.SUBID = C.SUBID AND C.ADDRESS = YYYY

--
那个会比较快??

---------------------------------------------
题目2:曾经看过网上有论文说用IN 和 EXISTS。。exists会比较快。。
因为IN会scan完全部value,才会在parent query process, 而EXISTS的道理是Yes or No。。
但是我发生过用IN的statistics IO 比较少。。反而EXISTS 的 statistics IO 还要高。。
有没有人遇到这样的问题?
回复

使用道具 举报


ADVERTISEMENT

发表于 14-9-2015 03:04 PM | 显示全部楼层
觉得应该是第二个比较快。。
如果你有加index和primary key。
回复

使用道具 举报

发表于 14-9-2015 11:19 PM | 显示全部楼层
本帖最后由 gkheng2003 于 14-9-2015 11:21 PM 编辑

我怀疑sql query plan 应该一样快 after optimizaton (at least 1st & 2nd i tried similar not same on MSSQL)

  1. SELECT  e.* FROM [HumanResources].[Employee] e, [Person].[Contact] c , [HumanResources].[EmployeeAddress] ea
  2. where c.[ContactID] = e.[ContactID]  and e.[EmployeeID] = ea.[EmployeeID] and LoginID = 'adventure-works\guy1'  
  3. -------------------------------------------------
  4. SELECT  e.* FROM [HumanResources].[Employee] e
  5. INNER JOIN [Person].[Contact] c
  6. ON c.[ContactID] = e.[ContactID]
  7. INNER JOIN [HumanResources].[EmployeeAddress] ea
  8. ON e.[EmployeeID] = ea.[EmployeeID]  
  9. where LoginID = 'adventure-works\guy1'  
复制代码


ur exetion plan? maybe can try "client statistics funcation"?
回复

使用道具 举报

 楼主| 发表于 15-9-2015 08:12 PM | 显示全部楼层
本帖最后由 阿福928 于 15-9-2015 08:13 PM 编辑
gkheng2003 发表于 14-9-2015 11:19 PM
我怀疑sql query plan 应该一样快 after optimizaton (at least 1st & 2nd i tried similar not same on MS ...

我的execution plan 是差不多一样 。。只是我想知道如果以performance 来看,那个比较快。。
我的意思。。如果我们比较注重query的performance。。我们会选择1,2 还是 3?
回复

使用道具 举报

发表于 16-9-2015 12:35 AM | 显示全部楼层
阿福928 发表于 15-9-2015 08:12 PM
我的execution plan 是差不多一样 。。只是我想知道如果以performance 来看,那个比较快。。
我的意思。 ...

as far as i know; 如果都是同样的 execution plan, it does not matter how u write it. MSSQL pulls at same speed.
unless u care on how much bytes u send to server?
回复

使用道具 举报

 楼主| 发表于 16-9-2015 06:41 PM | 显示全部楼层
gkheng2003 发表于 16-9-2015 12:35 AM
as far as i know; 如果都是同样的 execution plan, it does not matter how u write it. MSSQL pulls at ...

我关心的是logical read 和 phycical read 会有影响吗?还是这些reading是另外一回事。。
回复

使用道具 举报

Follow Us
发表于 16-9-2015 10:41 PM | 显示全部楼层
阿福928 发表于 16-9-2015 06:41 PM
我关心的是logical read 和 phycical read 会有影响吗?还是这些reading是另外一回事。。

not db expert
不过我怀疑2件事:
1) query execution plan is similar to Common-Runtime; thus C#/VBNET/Boo/j# should run with same speed if same IL code
2) phycical read  is more to table design (column size, normalization, ...) .  not on SP in this 1st case (2nd case IN & EXIST diff)
回复

使用道具 举报

发表于 19-9-2015 07:26 PM | 显示全部楼层
大家好

我先講下小弟的淺見, 我只有很少的MSSQL的經驗, 所以我說的不一定是準確的

如果資料量很大的話, 就以SQL語法來看, 我認為第三個的Query執行會比較迅速.

為何?
Join 3個table 的complexity 大致上會像下面那樣
  1. O(M*N*P)
复制代码
PS: M為table A的 row 數量, N為B的數量以此類推.

所以第三個語法會先篩選 table C的數量, 再來Join
以複雜度來看, P如果數量減少了之後, 整體是會快一些.

但是如果以table 設計來看(Normalize 或 data modeling)

A的 Primary Key(ID) = B的 Primary Key(ID), 意思就是:
  1. A  --1--<>--1-- B
复制代码
A 跟 B的關係是一對一, 這表示你把data set 拆成 A跟B根本就是多餘, 如果你不拆table , 你整體上的query 就只要Join兩個, 你就不需要那邊煩惱這個問題了.

別忘記Database Design 的最基礎口訣是:
Reduce Redundancy
Increase Efficiency
把資料分拆成兩個table 是要解決 Redundancy 的問題, 但是一定的程度上會減少Efficency,
既然你的data 不是一對多或多對多, 在設計的時候就不會去考慮分拆成A跟B兩個table.

當然你可以說
A跟B併起來Column 太多, 效率會變差, 拆出來會比較好.
但是如果是那樣, 又牽涉到另外一個設計模式的迷思, 等有機會我在說出來. 這裏我就不多說.

另外一個table C, 也是有明顯設計上的錯誤, 就是
  1. B. SubID = C.SubID
复制代码
如果B的SubID 跟C 的SubID 同樣屬於Unique的話, 情況就跟上面一樣, 一對一的table是不需要分拆的, 拆了等同脫褲子放屁.
也就是說你只要create 一個 ABC的table就好, 省略join的時間.

如果雙方不是Unique 的話, 這也是個問題, 就會造成 B跟C 的table 會是多對多的關係, 如下所示:
  1. B --m--<>--n-- C
复制代码
舉凡多對多的關係, 我們在ERD的表達會是這樣的
  1. B --m-- <B_C> --m-- C
复制代码

但是我們實際database migration 的時候會分別創立三個table
B (ID, Field1, Field2)
B_C (ID, B_ID, C_ID)
C(ID, Field1, Field2)

如果你堅持你那種table的設計, 當資料一多, 在join C 跟 B的時候一定就會出現預想以外的重複data, 本來複雜度應該 O(N*P) 但是會變成 O(N^P)

總結, 雖然你只是想問三個 join 的比較(其實答案很簡單), 但是你的前提(問題)在邏輯上是有很多沒有思考的地方, 就算是你裡真理很近, 但是你沒辦法驗證他, 因為你思考的方向本來就是錯的.

這讓我想起一句話:
想要得到好的答案, 先問對問題.



点评

受教了  发表于 26-9-2015 11:21 PM

评分

参与人数 1人气 +5 收起 理由
moot + 5

查看全部评分

回复

使用道具 举报


ADVERTISEMENT

发表于 30-10-2015 03:47 AM | 显示全部楼层
本帖最后由 moot 于 30-10-2015 03:51 AM 编辑

不同的DBMS Explain plan 都不同,内部优化后很可能一样。在Postgresql, mysql ,oracle,mssql 表现会完全不同。

逻辑上来说, 有index , WHERE A.NAME = XXXX  会优先.  没有的话,就会整个table select. WHERE A.NAME LIKE "%XXXX%" 是整个table A , 然后只找AND C.ADDRESS = YYYY

不过内部优化不会跟你这样说的。

DBMS 有时候经过多人的不同设计,会出现哭笑不得的情形。 #8楼的道理未必能符合你的需求, 要看B 对A 是否是1:1  ,是的话, 常用这SELECT , 把B和A merge 是正常的做法。 要不然,就把B SUBID  备份给A。 然后A就可以直接看到C . Reduce Redundancy 的  Normalisation 不是必然的。  Increase Efficiency  才是正道。denormalisation 的例子很多。

当然,这要看为何B 会成为这样的设计。比如说做full table scan report select , Table A 有个Column 很大,拉慢整体的update, 那就不得弄出一个sub table.(用redundancy disk space 抢速度). 不过用处必须被记录下来。可惜很多做程式设计的人, 都不喜欢做记录。 有些猪头会说, 我有放trigger update A 和B, 你看看就知道干什么。

评分

参与人数 1积分 +1 人气 +5 收起 理由
musicalangel + 1 + 5 看來先生也是同道之人, 失敬.

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 23-4-2024 02:05 PM , Processed in 0.073036 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表