我试图优化mysql查询,我用它来根据地址从数据库中获取客户。 这个问题让我很生气,所以我很感激帮助:)
我有两个与此查询相关的表:customers_address和systems_address。 我想只获得具有我可以为该系统显示的地址的客户。
示例:
我想从customers_address表中获取客户,其中address_id属于system_id 2.
使用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),如果我用subquerys值运行整个查询,它真的很快:
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;
任何使查询更快的方法???
以下是我运行波希米亚查询时的解释结果(创建新索引和更新后)。
ID:1个
select_type:SIMPLE
表:系统地址
类型:参考
possible_keys:address_id,system_id,address_id_system_id,idx1,
关键:IDX1
key_len:5
REF:常量
行:1999
额外:使用where;使用临时
ID:2
SELECT_TYPE:SIMPLE
表:customers_address
类型:REF
possible_keys:customer_id,address_id,address_id_customer_id,idx2
关键:address_id_customer_id
key_len:5
裁判:database.systems_address.address_id
行:45375个
额外:使用where;使用索引
答案 0 :(得分:1)
反转表的顺序并使用连接条件,其中包括额外条件:
select distinct customer_id
from systems_address
join customers_address on systems_address.address_id = customers_address.address_id
and customer_id != -1
where system_id = 2
这应该非常好,使用索引并最小化访问的行数。
确保定义了以下索引:
create index idx1 on systems_address(system_id);
create index idx2 on customers_address(address_id);
为了确保,还要更新统计信息:
analyze systems_address, customers_address;