如何解决MySQL预订网站:查询/数据库优化
似乎您正在寻找任何基于提供的开始/结束日期没有保留冲突的“对象”。进行coalcece()以始终包含保留中从未找到的那些对象是一个不错的选择,但是,作为左联接,我将尝试在找到日期的地方进行左联接,并忽略所有找到的对象。就像是
SELECT disTINCT
o.id
FROM
objects o
LEFT JOIN reservations r
ON o.id = r.object_id
AND ( r.from_date between '2012-04-05' and '2012-04-08'
OR r.to_date between '2012-04-05' and '2012-04-08' )
WHERE
o.location_id = 201
AND r.object_id IS NULL
LIMIT 20
我将确保通过(object_id,from_date)和另一个(object_id,to_date)在保留表上建立索引。通过显式地使用范围之间的from_date(以及迄今为止),您正在专门寻找占用此时间段的预留空间。如果找到它们,则不允许这样做,因此WHERE子句将查找“ r.object_id IS NULL”(即:在您提供的日期范围内未发现任何冲突)
从我先前的答案扩展,并通过在(id,from date)和(id,to date)上有两个不同的索引,您可以通过分别加入每个索引的保留并期望两个保留集中的NULL来获得更好的性能…
SELECT disTINCT
o.id
FROM
objects o
LEFT JOIN reservations r
ON o.id = r.object_id
AND r.from_date between '2012-04-05' and '2012-04-08'
LEFT JOIN reservations r2
ON o.id = r2.object_id
AND r2.to_date between '2012-04-05' and '2012-04-08'
WHERE
o.location_id = 201
AND r.object_id IS NULL
AND r2.object_id IS NULL
LIMIT 20
解决方法
在大多数查询中,我的表现都非常差。我已经阅读了很多关于stackoverflow的内容,但是仍然有一些问题,也许有人可以帮忙或者给我任何提示吗?
基本上,我正在预订网站上,除其他表格外,还有以下表格:
对象
+----+---------+--------+---------+------------+-------------+----------+----------+-------------+------------+-------+-------------+------+-----------+----------+-----+-----+
| id | user_id | status | type_id | privacy_id | location_id | address1 | address2 | object_name | short_name | price | currency_id | size | no_people | min_stay | lat | lng |
+----+---------+--------+---------+------------+-------------+----------+----------+-------------+------------+-------+-------------+------+-----------+----------+-----+-----+
或在MySQL中:
CREATE TABLE IF NOT EXISTS `objects` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'object_id',`user_id` int(11) unsigned DEFAULT NULL,`status` tinyint(2) unsigned NOT NULL,`type_id` tinyint(3) unsigned DEFAULT NULL COMMENT 'type of object,from object_type id',`privacy_id` tinyint(11) unsigned NOT NULL COMMENT 'id from privacy',`location_id` int(11) unsigned DEFAULT NULL,`address1` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,`address2` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,`object_name` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'given name by user',`short_name` varchar(12) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'short name,selected by user',`price` int(6) unsigned DEFAULT NULL,`currency_id` tinyint(3) unsigned DEFAULT NULL,`size` int(4) unsigned DEFAULT NULL COMMENT 'size rounded and in m2',`no_people` tinyint(3) unsigned DEFAULT NULL COMMENT 'number of people',`min_stay` tinyint(2) unsigned DEFAULT NULL COMMENT '0=no min stay;else # nights',`lat` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,`lng` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1451046 ;
预约
+----+------------+-----------+-----------+---------+--------+
| id | by_user_id | object_id | from_date | to_date | status |
+----+------------+-----------+-----------+---------+--------+
或在MySQL中:
CREATE TABLE IF NOT EXISTS `reservations` (
`id` int(11) NOT NULL AUTO_INCREMENT,`by_user_id` int(11) NOT NULL COMMENT 'user_id of guest',`object_id` int(11) NOT NULL COMMENT 'id of object',`from_date` date NOT NULL COMMENT 'start date of reservation',`to_date` date NOT NULL COMMENT 'end date of reservation',`status` int(1) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=890729 ;
有几个问题:
1-我没有设置任何其他键(主键除外)-我应该在哪里设置,我应该设置哪个键?
2-我已经了解了MyISAM与InnoDB的关系,对我来说,结论是MyISAM在只读方面更快,而InnoDB是为更经常获得UPDATED或INSERTs的表而设计的。因此,当前对象使用MyISAM并保留InnoDB。这是一个好主意吗?有更好的选择吗?
3-我需要查询在一定时期(在from_date和end_date之间)可用的那些对象。
但是,当我使用建议的解决方案时,查询会在返回任何结果之前超时(因此它确实很慢):
SELECT DISTINCT o.id FROM objects o LEFT JOIN reservations r ON(r.object_id=o.id) WHERE
COALESCE('2012-04-05' NOT BETWEEN r.from_date AND r.to_date,TRUE)
AND COALESCE('2012-04-08' NOT BETWEEN r.from_date AND r.to_date,TRUE)
AND o.location_id=201
LIMIT 20
我究竟做错了什么?进行此类查询的最佳解决方案是什么?其他网站如何做?我的数据库结构不是最适合此的还是仅仅是查询?
我还有其他问题,但我将非常感谢您对此提供的任何帮助!非常感谢您的任何提示或建议!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。