2017-10-09 132 views
1

我下載了Yelp數據集並將其放入MySQL,因爲我一直在使用的數據集太小而不得不考慮效率。我正試圖清除或意識到不良的SQL習慣,這將導致更大的數據集出現問題。這兩個查詢之間的效率或其他差異是什麼?

這裏是完全拉動相同的信息從數據庫中的方法有兩種:

USE yelp_db; 

SELECT name, hours FROM business 
LEFT JOIN hours 
ON business.id = hours.business_id; 
-- time taken 0,0025sec, 776071 rows returned 

SELECT name, hours FROM 
(SELECT name, id from business) AS b 
LEFT JOIN 
(SELECT hours, business_id from hours) AS h 
ON b.id = h.business_id; 
-- time taken 0,0015sec, 776071 rows returned 

這裏是輸出的一個示例:

John's Chinese BBQ Restaurant NULL 
Primal Brewery Monday|16:00-22:00 
Primal Brewery Tuesday|16:00-22:00 
Primal Brewery Friday|12:00-23:00 

第一種方法需要3行,但似乎比採用5行的第二種方法略慢。

無論是效率還是優雅,這些方法中的哪一種都是首選,爲什麼?

+1

像這樣的問題總是需要所有相關表的SHOW CREATE TABLE語句,以及每個查詢的EXPLAIN。另外,我會將from_hours和to_hours存儲在不同的列中。 – Strawberry

+0

我看了一下,EXPLAIN和SHOW CREATE TABLE有一天會有用,但是輸出很大,如果有人很好奇,schema是[here](https://www.yelp.com/dataset/documentation/sql)。 – cardamom

回答

2

第一種方法是優選的性能和優雅 - 你的結果不能承受。

我對時間有點懷疑。我預計超過一毫秒或兩個返回接近一百萬行。

在任何情況下,大多數MySQL版本(最新的可能是例外)都會實現子查詢。這爲查詢添加了額外的寫入和讀取層。它也可以防止使用索引。

至於優雅,不必要的子查詢對「優雅」無能爲力。這可能是一個意見問題,但我猜它是相當廣泛的。

+0

謝謝,我不能確定_materialize subqueries_的具體含義。在命令行中,時間可能更準確。坐在這裏的時間超過了幾分之一秒,感覺更像是十秒鐘,不知道爲什麼MySQL工作臺在撒謊,假設它顯示時間與處理時間。 – cardamom

+0

PS - 在命令行中重新運行它,mysql給出第一個爲2,20秒,第二個爲2,25秒。 – cardamom

+0

@cardamom。 。 。我猜你正在使用更新版本的MySQL,忽略了多餘的子查詢。 「物化」意味着子查詢基本上作爲新表運行和存儲。 –

1

只是爲了擴展@GordanLinoff的優秀答案,爲什麼你會看到這種差異。

如果按照顯示的順序運行它們,則從第一個數據緩存簡單的數據可以解釋時間。這種高速緩存可以發生在很多地方,一直到光盤控制器。

使用有用結果進行測試的唯一方法是在清除所有高速緩存後運行多次迭代並對結果進行平均。

+0

@cardamom運行每個查詢需要多長時間作爲 SELECT SQL_NO_CACHE ......? 這將消除查詢緩存的「效果」(如果可用)。 –

+1

@WilsonHauck - 停止編譯的SQL語句被緩存 - 與數據無關。我期望數據被緩存在(例如)磁盤或RAID控制器中。我們正在談論返回3/4百萬行10毫秒的差異。 – Hogan

+0

明天當我回到機器時,謝謝你再看一次。聽起來你們真的知道MySQL背後發生了什麼。好吧,有趣的是,你可以通過緩存來取消潛在的加速而不關閉MySQL並再次打開它。 – cardamom

相關問題