作者:丶平凡世界 SQL資料庫開發
上一講我們使用DISTINCT來去掉重複行以提高查詢效率,沒看過的小夥伴戳這裡
《
原創 | SQL優化之不查詢多餘的行和列》。
這和小夥伴們平常聽到的一條優化建議:盡量少使用DISTINCT相悖。下面我們來看看DISTINCT到底該不該使用。如果不想看處理過程的可以直接跳到紅色結論部分。
1.使用DISTINCT去掉重複資料
我們重複一下上一講的例子:
SELECT DISTINCT UnitPrice
FROM [Sales].[SalesOrderDetail]
WHERE UnitPrice>1000;
執行完之後的結果如下:

接下來,我們将這個表裡的資料增大到194萬條,再重複上面的實驗。
--将表SalesOrderDetail插入到一張實體表中
SELECT * INTO Sales.Temp_SalesOrder
FROM [Sales].[SalesOrderDetail] ;
--通過新增的實體表進行自循環插入3次,将資料增加到1941072行
DECLARE @i INT;
SET @i=0
WHILE @i<4
BEGIN
--這裡沒有将SalesOrderDetailID這個自增長的放在列中,是為了讓系統自動填充不同的數字進去,保證唯一性。
INSERT INTO Sales.Temp_SalesOrder
(SalesOrderID,CarrierTrackingNumber,OrderQty,ProductID,SpecialOfferID,
UnitPrice,UnitPriceDiscount,LineTotal,rowguid,ModifiedDate)
SELECT
SalesOrderID,CarrierTrackingNumber,OrderQty,ProductID,SpecialOfferID,
UnitPrice,UnitPriceDiscount,LineTotal,NEWID(),ModifiedDate
FROM Sales.Temp_SalesOrder
SET @i=@i+1;
END;
SELECT COUNT(1) FROM Sales.Temp_SalesOrder;
(提示:可以左右滑動代碼)
将SalesOrderDetailID的自增長屬性取消掉之後,插入1000條自身的資料,這樣我們就可以得到1000條重複的SalesOrderDetailID,相比1942072條記錄占比很小了
如下圖,将自增長辨別的是換成否後即可插入了。
INSERT INTO sales.Temp_Salesorder
SELECT TOP 1000 * FROM sales.Temp_Salesorder;
資料插入完整後,我們在将上一講的内容重複一下,看看效果如何?
A.在沒建索引的情況下,我們隻查詢UnitPrice這一列
SELECT UnitPrice FROM Sales.Temp_SalesOrder ;
我們看一下執行情況:
接下來是鑒證奇迹的時刻了,我們加DISTINCT在UnitPrice前面試試
SELECT DISTINCT UnitPrice FROM sales.Temp_Salesorder;
和之前的實驗結果一緻,在執行時間沒有多大差别的情況下,分析時間成倍的減少了。
B.當SalesOrderDetailID取消掉自增長屬性後就和普通列一樣了。
我們來重複上面的步驟:
SELECT SalesOrderDetailID FROM sales.Temp_Salesorder
執行完後結果如下:
與上面的UnitPrice沒使用DISTINCT情況基本一緻。
然後我們給SalesOrderDetailID加上DISTINCT後會怎麼樣呢?
SELECT DISTINCT SalesOrderDetailID
FROM sales.Temp_Salesorder
我們可以看到如下執行情況:
從上圖可以看到,DISTINCT已經排除了1000條記錄,但是在執行時花的時間比沒加DISTINCT更久了。
通過上述兩個實驗,我們可以得出這樣一條結論:在重複量比較高的表中,使用DISTINCT可以有效提高查詢效率,而在重複量比較低的表中,使用DISTINCT會嚴重降低查詢效率。是以并不是所有的DISTINCT都是降低效率的,當然你得提前判斷資料的重複量。
2.GROUP BY與DISTINCT去掉重複資料的對比
GROUP BY與DISTINCT類似,經常會有一些針對這兩個哪個效率高的争議,今天我們就将這兩個在不同重複資料量的效率作下對比。
A.重複資料量多的情況下,對UnitPrice進行去重
SELECT DISTINCT UnitPrice FROM sales.Temp_Salesorder;
SELECT UnitPrice FROM sales.Temp_Salesorder GROUP BY UnitPrice;
将上述兩條語句一起執行,結果如下:
可以看出兩條語句對應的執行時間GROUP BY比DISTINCT效率高一點點。
B.重複資料量少的情況下,對SalesOrderDetailID進行去重
SELECT DISTINCT SalesOrderDetailID FROM sales.Temp_Salesorder
SELECT SalesOrderDetailID FROM sales.Temp_Salesorder
GROUP BY SalesOrderDetailID
也是同時執行上述兩條語句,其結果如下:
作者對上述語句同時執行多次,針對重複量多的UnitPrice,GROUP BY總的處理效率比DISTINCT高一點點,但是針對重複量低的SalesOrderDetailID,DISTINCT就比GROUP BY快一點了,而如果随着整體資料量的增加,效果會越來越明顯。