我试图优化我用来根据地址从数据库中获取客户的 mysql 查询。这个问题让我发疯,所以我会很感激帮助:)
我有两个与此查询相关的表:customers_address 和 systems_address。我只想获得具有我可以为该系统显示的地址的客户。
例子:
我想从customers_address表中获取客户,该表具有属于system_id 2的address_id。
使用 in 子句的最佳查询:
select distinct customer_id from customers_address use index(address_id_customer_id) where address_id in (select distinct address_id from systems_address where system_id = 2) and address_id !=-1\G;
事情是子查询只返回一行(值2),如果我用子查询值运行整个查询,它真的很快:
select customer_id from customers_address use index(address_id_customer_id) where address_id !=-1 and address_id in (2)\G;
时间从超过 10 秒下降到 0.00 秒。
我也尝试过使用连接进行查询,但是当我将值替换为 in 子句时,与查询相比,它的性能仍然很慢(超过 7 秒)。下面是带有连接的相同查询:
select distinct customer_id from customers_address use index(address_id_customer_id) inner join systems_address where systems_address.address_id = customers_address.address_id and system_id = 2 and customer_id != -1\G
我已将 customers_address 816 000 行和 systems_address 400 000 行放入。这些表的以下模式(表简化了该问题更容易找到):
create table systems_address (
`id` int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`address_id` int(11) DEFAULT NULL,
`system_id` INTEGER(11)DEFAULT NULL,
KEY `address_id` (address_id),
KEY `system_id` (system_id))
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
create table customers_address (
`id` int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`customer_id` int(11) DEFAULT NULL,
`address_id` INTEGER(11)DEFAULT NULL,
KEY `customer_id` (customer_id),
KEY `address_id` (address_id),
KEY `address_id_customer_id` (address_id,customer_id),
FOREIGN KEY (`address_id`) REFERENCES `systems_address` (`address_id`) ON UPDATE CASCADE ON DELETE SET NULL)
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
有什么方法可以让查询更快???
这是我运行 Bohemian 的查询时的解释结果(在创建这些新索引和更新之后)。
id:1
select_type: SIMPLE
table: 系统地址
类型: ref
possible_keys: address_id, system_id, address_id_system_id,idx1, key:idx1 key_len:5 ref:const rows:1999 Extra:Using where;Using Temporary
id:2
select_type:SIMPLE
table:customers_address
type:ref
possible_keys:customer_id, address_id, address_id_customer_id,idx2
key:address_id_customer_id
key_len:5
ref:database.systems_address.address_id
rows:45375
Extra: Using where;Using index