在我的网站上,我有一个查询构建工具,用户可以在其中拖放块以形成基本(和已清理的!)SQL查询。上周有人创建了这个看似良性的查询,将所有其他查询挂起到他们的模式(使整个系统无法使用):
SELECT clients.id_client
FROM clients
INNER JOIN cases ON clients.id_client=cases.id_client
INNER JOIN locations ON clients.id_client=locations.id_client
WHERE cases.date>=1444176000 OR locations.type IN (7)
我使用GCE LAMP堆栈标准实例。它通常以10%的CPU利用率运行。在我的客户打电话给我说没有人能够访问系统之前,它将它飙升100%并保持在那里几个小时。
clients表有25,000个条目。案件有55,000。地点有20,000。
所以......好吧,我明白了...加入这三个表需要一些时间。但是在对出错的地方运行一些测试时,我尝试用AND替换OR以产生:
SELECT clients.id_client
FROM clients
INNER JOIN cases ON clients.id_client=cases.id_client
INNER JOIN locations ON clients.id_client=locations.id_client
WHERE cases.date>=1444176000 AND locations.type IN (7)
然后在不到一秒钟内回来了。
为什么使用AND需要十分之一秒但使用OR需要两个多小时?对于这两个查询,mySQL是否仍然需要首先加入所有三个表才能产生最终结果?
值得注意的是,删除位置表的实际使用情况不会崩溃:
SELECT clients.id_client
FROM clients
INNER JOIN cases ON clients.id_client=cases.id_client
INNER JOIN locations ON clients.id_client=locations.id_client
WHERE cases.date>=1444176000
删除案例表ALMOST的实际用法时:
SELECT clients.id_client
FROM clients
INNER JOIN cases ON clients.id_client=cases.id_client
INNER JOIN locations ON clients.id_client=locations.id_client
WHERE locations.type IN (7)
使用那个,服务器最大为100%,同一模式的所有其他连接都被冻结,但结果在大约2.5分钟内返回(即使phpMyAdmin声称它只花了不到一秒)并且一切恢复正常。
同样,案例表要大得多,并且列数比位置表多得多。所以我猜想保留WHERE中的case表会比保留位置表更有问题。