sql查询很慢
Posted
技术标签:
【中文标题】sql查询很慢【英文标题】:sql query is slow 【发布时间】:2011-11-18 19:22:48 【问题描述】:我有一个 phpmyadmin 数据库,其中包含 1 000 000 条记录,我需要在其中搜索。每周都会添加 500 000 条记录。
所以,这就是我需要的:
location_id value date time name lat lng
3 234 2011-11-18 19:50:00 Amerongen beneden 5.40453 51.97486
4 594 2011-11-18 19:50:00 Amerongen boven 5.41194 51.97507
我用这个查询来做这个:
SELECT location_id, value, date, time, locations.name, locations.lat, locations.lng FROM
(
SELECT location_id, value, date, time from `measurements`
LEFT JOIN units ON (units.id = measurements.unit_id)
WHERE units.name='Waterhoogte'
ORDER BY measurements.date DESC, measurements.time DESC
) as last_record
LEFT JOIN locations on (locations.id = location_id)
GROUP BY location_id
这需要 30 秒。我该如何改进呢?这是我的结构:
CREATE TABLE IF NOT EXISTS `locations` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`code` varchar(255) NOT NULL,
`lat` varchar(10) NOT NULL,
`lng` varchar(10) NOT NULL,
`owner_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=244 ;
-- --------------------------------------------------------
--
-- Table structure for table `measurements`
--
CREATE TABLE IF NOT EXISTS `measurements` (
`id` int(11) NOT NULL auto_increment,
`date` date NOT NULL,
`time` time NOT NULL,
`value` varchar(255) NOT NULL,
`location_id` int(11) NOT NULL,
`unit_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=676801 ;
-- --------------------------------------------------------
--
-- Table structure for table `owner`
--
CREATE TABLE IF NOT EXISTS `owner` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
-- --------------------------------------------------------
--
-- Table structure for table `units`
--
CREATE TABLE IF NOT EXISTS `units` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`unit_short` varchar(255) NOT NULL,
`owner_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=44 ;
phpmyadmin 可以处理的限制是多少?
【问题讨论】:
我想澄清这不是 phpmyadmin 的限制。这是 mysql 运行查询的速度。 注意:phpmyadmin 不是数据库。它是一个基于 PHP 的 INTERFACE 到 mysql 数据库服务器。 【参考方案1】:在units.name 上创建索引是一个好的开始。 您还应该真正重新考虑要撤回的数据量。 真的有人会筛选那么多记录吗?更改您的查询以限制记录数并考虑涉及分页机制的 UI 界面。
【讨论】:
我将 WHERE units.name='Waterhoogte' 替换为:WHERE units.id=4,将其缩短到 2 秒。还有其他方法可以更好地重写此查询吗? 你有这个字段的索引吗?您可能还希望在 location.id 上有一个索引。最终,您可以做更多的事情来使您的查询“更快”。更多的是您将多少记录带回客户的问题。限制它并编写一些漂亮的 UI,在需要时触发更多记录。带回这么多记录是不行的。当您进行 google 搜索并返回 40 页结果时,大多数情况下您只关心前 2 页,甚至是第二页。 好的,谢谢大家! : 显示第 0 - 29 行(总共 30 行,查询耗时 1.4580 秒),我可以忍受这个 @Melvin - 对我来说这相当快。【参考方案2】:您需要在units.name 上放置一个索引或唯一索引。
【讨论】:
【参考方案3】:添加以下索引:
unit.name 和 unit.id 上的复合索引(覆盖索引)。 测量.日期和测量.时间的复合索引。 location.id 上的索引
【讨论】:
【参考方案4】:您应该首先尝试在units.name 上创建索引。但要明白,索引是有折衷的——读操作会更快,但它会减慢写操作的速度。如果您对此感到担忧,或者您受到写入缓慢的影响,那么您可能需要尝试在units.name 中使用较少数量的字符创建索引。
例如,要在 units.name 的前 12 个字符上声明索引,您需要声明以下内容:
CREATE INDEX first_twelve ON units (name(12));
同样,如果您没有注意到仅添加索引会产生任何不良影响,则可能没有必要这样做,但请记住这一点。
【讨论】:
【参考方案5】:SELECT measurements.location_id, measurements.value, measurements.date, measurements.time, locations.name, locations.lat, locations.lng
FROM measurements
LEFT JOIN units ON units.id = measurements.unit_id
LEFT JOIN locations ON locations.id = measurements.location_id
WHERE units.id = 4
GROUP BY measurements.location_id
ORDER BY measurements.date DESC, measurements.time DESC
【讨论】:
谢谢,它更快,但显示 ASC 的“测量”记录,我想要最新的记录。 order by 需要在 group by 之前发生。我无法弄清楚这是如何工作的。这个查询实际上是我首先提出的。 @Melvin 在 where 子句中有子查询可能会更快。date = select max date
。然后你可以摆脱你的分组和排序。将您的日期和时间放在一个日期时间字段中也会更快,但这是另一回事。以上是关于sql查询很慢的主要内容,如果未能解决你的问题,请参考以下文章