2017-10-09 136 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

相关问题