我正在使用 python,sqllite3我想知道這個查詢的性能是否可以提高?
main約 100,000 行的表
0 1 2 3 4 Amount
0 0 9 12 6 60 40800.0
1 0 9 12 6 61 40100.0
2 0 9 12 6 65 39900.0
3 0 9 12 6 74 40300.0
4 0 9 12 7 60 40600.0
util表 ~75,000 行
0 1 2 Amount
0 78 75 65 9900.0
1 80 75 65 9900.0
2 80 72 65 10000.0
3 78 72 65 10000.0
4 79 75 65 10000.0
該查詢當前獲取兩個表的笛卡爾積,其中金額的總和在 49,700 和 50,000 之間,如果我的理解正確,則獲取前 200,000 個匹配項。
con = sqlite3.connect(':memory:')
df.to_sql(name='main', con=con)
df1.to_sql(name='util', con=con)
query = '''
SELECT *
FROM main AS m
INNER JOIN
util AS u
ON
50000 >= m.Amount u.Amount
AND
49700 <= m.Amount u.Amount
LIMIT
200000;
'''
final_df = pd.read_sql_query(query, con)
uj5u.com熱心網友回復:
由于您不是在列值上匹配,而是在運算式上m.Amount u.Amount匹配,因此必須為兩個表之間的每個可能的行組合(100k * 75k = 7500mil 或 75 億個組合)計算它。您實際上得到的是 CROSS JOIN,因為您在兩個表之間的任何列上都不匹配。
1.您可以確保運算式只計算一次,而不是使用運算子對 AND 子句50000 >= m.Amount u.Amount&的每個部分進行計算。為了清楚起見,我只是標準的“來自table1,table2” :49700 <= m.Amount u.AmountBETWEENWHERE
SELECT * FROM main AS m
INNER JOIN
util AS u
ON
m.Amount u.Amount BETWEEN 49700 AND 50000
;
2.您必須使用其他方法來減少檢查的行數。例如,當Amount任何一個表超過 50,000 時,它不可能是匹配的,因此它會在驗證的早期被排除,并且通過不計算m.Amount u.Amount一次來節省時間:
SELECT * FROM main AS m, util AS u
WHERE
m.Amount <= 50000
AND
u.Amount <= 50000
AND
m.Amount u.Amount BETWEEN 49700 AND 50000
;
如果金額不能為 0,則將 更改<= 50000為< 50000。
3.您可以做其他事情,例如找到每個表中的最小金額,然后確保另一個表的金額小于50000 - that first min amt。
4.使用“2 個數字之和”問題,您可以一次性計算其中一張表的最小匹配 Amt 和最大匹配 Amt(添加兩個新列),然后使用 BETWEEN 檢查使用來自的 Amt另一張桌子。它仍然需要進行交叉連接,但評估每個匹配的 cpu 時間減少了。
ALTER TABLE main ADD COLUMN min_match INT default 0;
ALTER TABLE main ADD COLUMN max_match INT default 0;
UPDATE main SET min_match = 49700 - Amount,
max_match = 50000 - Amount;
SELECT * FROM main AS m, util AS u
WHERE
u.Amount BETWEEN m.min_match AND m.max_match
;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/430931.html
