我有以下查询,大约需要一分钟才能运行:
SELECT * FROM main_i i JOIN main_p p ON p.item_id=i.id
WHERE COALESCE(p.provider_title_id, i.provider_title_id) = "X"
虽然这看起来很简单,但要花很长时间才能运行,而我能够解决的唯一方法是使用以下方法:
SELECT * FROM main_i i JOIN main_p p ON p.item_id=i.id
WHERE p.provider_title_id = "X"
UNION
SELECT * FROM main_i i JOIN main_p p ON p.item_id=i.id
WHERE i.provider_title_id = "X" AND p.provider_title_id IS NULL
这瞬间完成,但是查询看起来如此愚蠢,以至于必须有更好的方法来执行此操作。
我在这里应该使用什么?
答案 0 :(得分:1)
在您的第一个查询中,谓词import pandas as pd
lines = [] # Declare an empty list named "lines"
with open ('03-22-2019.txt', 'rt') as in_file: # Open file
for line in in_file: # For each line of text in in_file, where the data is named "line",
lines.append(line.rstrip('\n')) # add that line to our list of lines, stripping newlines.
while('' in lines):
lines.remove("")
lines = [x for x in lines if 'A123' not in x] #delete all lines with 'A123'
for element in lines: # For each element in our list,
print(element) # print it.
split_line = lines[0].split() # create list with serial number line
Serial_Num = split_line[-1]
print(Serial_Num)
split_line = lines[1].split() # go to line with CMS SN
CMS_SN = split_line[-1]
print(CMS_SN)
split_line = lines[2].split()
Firm_Rev_1 = split_line[-1]
Firm_Rev_2 = split_line[-2]
print(Firm_Rev_1)
print(Firm_Rev_2)
# Problem section starts here!
start_data = lines.index("log =") + 1 #<<<<<<<<<<
data = [x for x in lines[start_data:].split(",")] #<<<<<<<<<<
#dfObj = pd.DataFrame(lines[start_data:-1].split(",")) #<<<<<<<<<<
基于两个表中的列。这迫使MySQL使用此谓词作为“过滤谓词”,而不是“访问谓词”。
这在英语中是什么意思?这意味着MySQL使用[希望很快]访问谓词执行由COALESCE(p.provider_title_id, i.provider_title_id) = "X"
产生的叉积,但是随后它被迫使用上述条件过滤整个结果集。叉积可能导致大量行将被该条件丢弃。进行大量工作,但成效不大。
第二个查询使用MySQL能够用来访问行的简单谓词。这次仅访问了几行。谓词对它们进行过滤,但是工作量非常有限。
如果您生成并比较每个查询的执行计划,您会发现这一点更加清晰。
答案 1 :(得分:1)
以我的经验,使用函数(例如COALESCE)可停止db引擎以预先优化行选择。数据库引擎无法确定最终结果,除非它们运行通过此类功能联接表而产生的每条记录。相反,对于第二个查询,db引擎完全知道在创建初始集时(在应用位置之前)要过滤的内容。您也许可以在查询说明计划中选择它。
如您所知,接下来是实现相同结果的另一种方法。这应该可以证明事实的速度更快。
SELECT *
FROM main_i i JOIN
main_p p
ON p.item_id = i.id
WHERE p.provider_title_id = 'X'
OR
(p.provider_title_id IS NULL
AND i.provider_title_id = 'X')
答案 2 :(得分:0)
这很好,但是您应该使用UNION ALL
:
SELECT *
FROM main_i i JOIN
main_p p
ON p.item_id = i.id
WHERE p.provider_title_id = 'X'
UNION ALL
SELECT *
FROM main_i i JOIN
main_p p
ON p.item_id = i.id
WHERE i.provider_title_id = 'X' AND p.provider_title_id IS NULL;
此版本允许优化器查看两个更简单的子查询。每个子查询可以利用一组不同的索引。通常,SQL在OR
条件下处理不等式和JOIN
时表现不佳。