连接多个大表时如何进行更快的查询?

Posted

技术标签:

【中文标题】连接多个大表时如何进行更快的查询?【英文标题】:How to make a faster query when joining multiple huge tables? 【发布时间】:2019-08-28 01:21:41 【问题描述】:

我有 3 张桌子。所有 3 个表都有大约 200 万行。每天输入 10,000-100,000 个新条目。完成下面的 sql 语句大约需要 10 秒。有没有办法让这条sql语句更快?

SELECT customers.name
FROM customers
INNER JOIN hotels ON hotels.cus_id = customers.cus_id
INNER JOIN bookings ON bookings.book_id = customers.book_id
WHERE customers.gender = 0 AND
customers.cus_id = 3
LIMIT 25 OFFSET 1;

当然,这个语句可以正常工作,但是速度很慢。有没有更好的方法来编写这段代码?

【问题讨论】:

在两个表中添加索引并重试,按时跟踪或参考此 [***.com/questions/2955459/what-is-an-index-in-sql] @M.Hemant 子查询是否也有助于它变得更快? 我觉得“hotels”表有一个 cust_id 有点奇怪。期望在预订表中为客户提供索引 FK。 @LukStorms 这只是我想到的一个简单示例。这不是我的实际桌子(也不是关于酒店的)。我的实际表在需要的地方有适当的 FK 和 PK。我只是想让问题尽可能简单和最小化。这些列只是为了使问题最小化。 EXPLAIN 的输出在哪里?你的innodb_buffer_pool_size 的价值是多少?你有多少内存?硬盘呢? HDD 的品牌/型号/IOPS/带宽是多少?这是 I/O 绑定查询的一个明显案例,基本前提是增加 mysql 可以利用的内存。使用EXPLAIN 查看优化器的作用以及是否可以索引字段以帮助查询。 【参考方案1】:

所有数据库服务器都有一种优化引擎,它将确定如何最好地获取您想要的数据。使用诸如您显示的 select 之类的简单查询,没有任何方法可以大大提高 SQL 的性能。正如其他人所说,子查询无济于事,因为它会被优化到与连接相同的计划中。

如果可以的话,减少列数、添加索引、加强服务器。

考虑缓存。我不是 mysql 专家,但发现这篇文章很有趣,值得一读。 https://www.percona.com/blog/2011/04/04/mysql-caching-methods-and-tips/

查看汇总表部分并考虑是否合适。是否需要及时了解每个酒店、客户和预订,或者将其插入到汇总表中,每小时一次就可以了?

【讨论】:

【参考方案2】:

子查询无济于事,但适当的索引可以提高性能,因此请确保您拥有适当的索引

 create  index  idx1 on customers(gender , cus_id,book_id, name )

 create index  idex2 on hotels(cus_id)

 create index  idex3 on hotels(book_id)

【讨论】:

【参考方案3】:

我很难相信这与实际问题有关。正如所写,我希望这会一遍又一遍地返回相同的客户名称。

我会推荐以下索引:

customers(cus_id, gender, book_id, name) hotels(cus_id) bookings(book_id)

bookings 不去酒店真的很奇怪。

首先,这些索引覆盖了查询,因此不需要访问数据页。逻辑是从where 子句开始并首先使用这些列。然后从 onselect 子句添加其他列。

hotelsbookings 仅使用一列,因此这些索引是微不足道的。

在没有ORDER BY 的情况下使用OFFSET 非常可疑。无论如何,结果集的顺序是不确定的,因此没有理由跳过名义上的“第一个”值。

【讨论】:

以上是关于连接多个大表时如何进行更快的查询?的主要内容,如果未能解决你的问题,请参考以下文章

mysql把一个大表拆分多个表后,如何解决跨表查询效率问题

我应该避免在查询大表时使用 ORDER BY 吗?

如何使用具有多个 GROUP BY、子查询和 WHERE IN 在大表上的查询来优化查询?

如何在连接多个表时使用 GROUP BY 连接字符串?

使用带有活动记录的连接表时如何连接模型的多个实例?

加入大表时,postgres 查询速度慢