当前位置: 首页 > 面试题库 >

MySQL预订网站:查询/数据库优化

姚韬
2023-03-14
问题内容

在大多数查询中,我的表现都非常差。我已经阅读了很多关于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

我究竟做错了什么?进行此类查询的最佳解决方案是什么?其他网站如何做?我的数据库结构不是最适合此的还是仅仅是查询?

我还有其他问题,但我将非常感谢您对此提供的任何帮助!非常感谢您的任何提示或建议!


问题答案:

似乎您正在寻找任何基于提供的开始/结束日期没有保留冲突的“对象”。进行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


 类似资料:
  • 本文向大家介绍MySQL数据库查询性能优化策略,包括了MySQL数据库查询性能优化策略的使用技巧和注意事项,需要的朋友参考一下 优化查询 使用Explain语句分析查询语句 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。 通过对查询语句的分析,可以了解查询语句的执行情况,找出查询语句执行的瓶颈,从而优化查询语句. 使用索引查询 MySq

  • 本文向大家介绍优化MySQL数据库中的查询语句详解,包括了优化MySQL数据库中的查询语句详解的使用技巧和注意事项,需要的朋友参考一下 很多时候基于php+MySQL建立的网站所出现的系统性能瓶颈往往是出在MySQL上,而MySQL中用的最多的语句就是查询语句,因此,针对MySQL数据库查询语句的优化就显得至关重要!本文就此问题做出详细分析如下: 1、判断是否向MySQL数据库请求了不需要的数据,

  • 主要内容:1 优化数据访问,2 重构查询,2.1 优化子查询,2.2 优化GROUP BY和DISTINCT,2.3 优化LIMIT分页,2.4 优化UNION简单介绍了一些常见MySQL数据库优化手段,比如减少数据访问、使用索引、使用关联查询等等。 1 优化数据访问 查询性能低下的最基本原因就是访问了太多数据,一些查询要不可避免地筛选大量的数据,大部分性能欠佳的查询都可以用减少数据访问的方式进行优化,这是最简单也是很有效的优化方式。 首先分析应用程序是否正在获取超过需要的数据,这通常表现在获取

  • 我在mysql中有这些数据。 我想调整数据并将其发送到json使用节点js / expressjs与每日,每月,每年的总和。 首先我尝试这个查询。 这个查询运行良好。但我认为这是浪费。因为反复查询代码数量。 输出: 我可以用一个查询获取所有数据吗? 最后,我想用Expresjs发送这种形式的数据。 或此表单 我尝试过mysql查询,sequelize,洛达什。但我找不到正确的方法。

  • 我试图使用下面的MySQL语句

  • 1 基本步骤 基准测试 生产环境分析 数据库优化 2 基准测试 采用sysbench进行基准测试 常用sysbench基准测试命令: 2.1 性能指标 常用的性能指标包括: 吞吐量:TPS 延迟 并发 3 生产环境分析 4 常用MySQL性能优化 4.1 SQL语句优化 4.1.1 索引优化 4.1.2 表结构设计优化 4.2 MySQL配置优化