mysql查询内部连接
我有以下数据库结构:mysql查询内部连接,mysql,performance,mysql-slow-query-log,Mysql,Performance,Mysql Slow Query Log,我有以下数据库结构: CREATE TABLE IF NOT EXISTS `business` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `address` varchar(255) NOT NULL, `city` varchar(255) NOT NULL, `state` varchar(255) NOT NULL, `postal` int(11) NOT NULL, `country` varchar(255) NO
CREATE TABLE IF NOT EXISTS `business` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`address` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`state` varchar(255) NOT NULL,
`postal` int(11) NOT NULL,
`country` varchar(255) NOT NULL,
`lat` float NOT NULL,
`lng` float NOT NULL,
`name` varchar(255) NOT NULL,
`phone` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`website` varchar(255) NOT NULL,
`userID` bigint(20) NOT NULL,
`url` varchar(255) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`clicks` bigint(20) NOT NULL,
`oHours` varchar(255) NOT NULL,
`featured` tinyint(1) NOT NULL,
`imageThumb` varchar(255) NOT NULL DEFAULT 'default.jpg',
`imageOrig` varchar(255) NOT NULL DEFAULT 'default.jpg',
`flag` tinyint(1) NOT NULL,
`display` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=589846 ;
此表(业务)有507736条记录
CREATE TABLE IF NOT EXISTS `businesscat` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bizID` bigint(20) NOT NULL,
`catID` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=589863 ;
此表(businesscat)有519825条记录
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`icon` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
此表(类别)只有5条记录
所以,我的问题是,我试图通过使用ff计算最近的业务来获得100条记录:
SELECT business.name
, business.lng
, business.lat
, business.address
, business.city
, business.state
, business.postal
, business.phone
, business.url
, business.imageThumb
, businesscat.catID
, category.icon
, (((acos(sin((".$lat."*pi()/180))
* sin((business.lat*pi()/180))
+ cos((".$lat."*pi()/180))
* cos((business.lat*pi()/180))
* cos(((".$lng."-business.lng)*pi()/180))))
* 180/pi())*60*1.1515) AS distance
FROM business
INNER JOIN businesscat ON businesscat.bizID=business.id
INNER JOIN category ON category.id=businesscat.catID
ORDER BY distance LIMIT 100
有没有办法加快速度 我刚刚在MySQL手册中读到,子查询可以包含orderby和LIMIT。因此,我的建议如下: 将距离计算与ORDER BY和LIMIT子句一起放在单独的子查询中。然后,将联接放在封闭(外部)查询中。这样一来,您的加入操作将不会针对您感兴趣的领域之外的数十万家企业执行 还要确保为businesscat.bizID和businesscat.catID定义了索引 编辑:如果这不能使您的查询足够快,请尝试以下操作:
在进入查询之前,计算“最小”和“最大”经纬度(在$lng和$lat的北面、西面、东面和南面各100米处),然后,使用这些选项在内部查询中预筛选您的业务,如下所示:
WHERE business.lng>=$min\u lng和business.lng=$min\u lat和business.lat您知道在bigint中可以存储多少数据吗?这对整个宇宙都足够了。
Smallint或者mediumint都不错
All of the fields have varchar(255)! do you really need that much data?
您可以缓存mySQL查询执行计划,您使用它吗
您的表的存储引擎是InnoDB,所以让我问您一个更重要的问题:
Do you use innodb_file_per_table setting?
为联接中按顺序使用的每个字段编制索引:
- 距离没有索引
- 用户ID未编入索引
编辑
你真的确定吗,我建议你仔细检查一下mySQL手册。我很确定这一点,很高兴知道我现在检查了它,varchar(255)肯定不同于varchar(20)
我认为您混淆了INT(20)=>INT和Varchar(255)=>Varchar(20)如果不按距离排序,我认为所有运行都正常?您是否为businesscat.bizID和businesscat.catID定义了索引?另外,您可以通过删除id并声明bizID和catID为主键来优化businesscat表,尽管我怀疑这是否会改善您的查询。我将BIGINT更改为INT,这样可以吗?雷内,你说得对。当我按距离删除订单时,它的加载速度更快。MikeNakis有一个要点。你需要两个索引,否则它会遍历所有表中的所有行。现在很好用。我按距离添加订单,效果很好。谢谢大家!“var char”。最大值是多少并不重要,尤其是。我现在检查了它,MySQL将我的数据构建到我指定的位置!是的,我正在使用innodb_file_per_table设置。我已经为bizID和catID编制了索引。同样,非常慢。而且你的链接是无关的@TomalakGeret'kalAs@MikeNakis告诉我们,你应该预先计算你的长lat,让MySQL缓存你的结果。