[英]Joining Tables in MySQL (slow)
我正在嘗試將一些數據保存在 2 個單獨的表中,然后將它們與參考表連接起來。
我的數據如下所示(搜索查詢和頁面 URL):
[
['widget', 'www.example.com/widgets'],
['blue widget', 'www.example.com/blue-widgets'],
['red widget', 'www.example.com/widgets'],
['widget', 'www.example.com/green-widgets'],
['orange widget', 'www.example.com/widgets'],
]
如您所見,一些搜索查詢被分配給多個頁面,考慮到這一點以及其他一些客戶端性能原因,我想將搜索查詢和頁面 URL 拆分到單獨的表中,但要跟蹤哪個搜索查詢,屬於哪個頁面網址。
為此,到目前為止,我有以下 2 個表(unique_key 列只是哈希以阻止添加重復項):
CREATE TABLE queries (
id BIGINT NOT NULL AUTO_INCREMENT,
query VARCHAR(400) collate utf8_bin,
unique_key varchar(100) unique,
PRIMARY KEY (id));
CREATE TABLE pages (
id BIGINT NOT NULL AUTO_INCREMENT,
page VARCHAR(2083),
unique_key varchar(100) unique,
PRIMARY KEY (id));
insert into queries (query, unique_key) values
('widget', '1234'),
('widgets', '1233'),
('blue widget', '3243'),
('red widget', '5432'),
('green widget', '4642');
insert into pages (page, unique_key) values
('www.example.com/widgets', '7895'),
('www.example.com/widgets-1', '4569'),
('www.example.com/widgets-2', '4568'),
('www.example.com/widgets-3', '1254'),
('www.example.com/widgets-4', '6527');
然后,為了構建將查詢與頁面相關聯的 pivot 表,我這樣做:
CREATE TABLE page_query_join (
id BIGINT NOT NULL AUTO_INCREMENT,
query_id int,
page_id int,
PRIMARY KEY (id));
insert into page_query_join (query_id, page_id)
values ((select id from queries where query='widget' limit 1), (select id from pages where page='www.example.com/widgets' limit 1)) ON DUPLICATE KEY UPDATE query_id=query_id
這一切都是在 Python 腳本中完成的,在該腳本中,我基本上創建了 hash 鍵,在一個循環中插入所有搜索查詢,然后在另一個循環中插入所有頁面 URL,然后最后一次循環並執行最終查詢以加入他們。
此最終查找的完整 function 如下所示:
def add_query_page_join(self, data):
sql = '''insert into page_query_join (query_id, page_id)
values ((select id from queries where query=%s limit 1), (select id from pages where page=%s limit 1)) ON DUPLICATE KEY UPDATE query_id=query_id'''
try:
# Execute the SQL command
self.cursor.executemany(sql, data)
# Commit your changes in the database
self.db.commit()
#return self.cursor.lastrowid
except Exception as e:
# Rollback in case there is any error
self.db.rollback()
finally:
self.db.close()
data
變量如下所示:
data = [
['widget', 'www.example.com/widgets'],
['blue widget', 'www.example.com/blue-widgets'],
['red widget', 'www.example.com/widgets'],
['widget', 'www.example.com/green-widgets'],
['orange widget', 'www.example.com/widgets'],
]
我的數據變量一次通過 1,000 個項目,但我每天總共有大約 100 萬個項目要做。 我當前的版本需要幾個小時才能完成。
我可以做些什么來提高連接表查詢的性能,或者只是我將所有內容添加到表中的方式(也許有一種方法可以一次插入所有 3 個表?)
感謝您的幫助 - 任何缺少的東西都讓我知道。
在join
查詢上更新說明:
+----+-------------+---------+------+---------------+-------+---------+-------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+-------+---------+-------+------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 3 | SUBQUERY | pages | ALL | NULL | NULL | NULL | NULL | 8641 | Using where |
| 2 | SUBQUERY | queries | ref | query | query | 768 | const | 1 | Using where |
+----+-------------+---------+------+---------------+-------+---------+-------+------+----------------+
目前尚不清楚您在做什么,但您顯然需要
queries: INDEX(query, id) -- This seems to exist
pages: INDEX(page, id) -- Definitely missing
但是,由於page
太大而無法索引,請考慮將unique_hash
更改為PRIMARY KEY
(並完全擺脫當前的id
)。
同時,您有一個沒有ORDER BY
的LIMIT
; 你在乎你得到什么東西嗎?
闡述:
我假設您已將數據加載到名為 widget_url_pairs 的表中。 這是一個模擬...
USE test;
DROP TABLE IF EXISTS widget_url_pairs;
CREATE TABLE widget_url_pairs
(widget VARCHAR(100) NOT NULL
,url VARCHAR(200) NOT NULL
,PRIMARY KEY(widget,url)
);
INSERT IGNORE INTO widget_url_pairs VALUES
('widget', 'www.example.com/widgets'),
('blue widget', 'www.example.com/blue-widgets'),
('red widget', 'www.example.com/widgets'),
('widget', 'www.example.com/green-widgets'),
('orange widget', 'www.example.com/widgets');
DROP TABLE IF EXISTS widgets;
CREATE TABLE widgets
(widget_id SERIAL PRIMARY KEY
,widget VARCHAR(100) NOT NULL UNIQUE
);
INSERT INTO widgets (widget) SELECT DISTINCT widget FROM widget_url_pairs;
DROP TABLE IF EXISTS urls;
CREATE TABLE urls
(url_id SERIAL PRIMARY KEY
,url VARCHAR(200) NOT NULL UNIQUE
);
INSERT INTO urls(url) SELECT DISTINCT url FROM widget_url_pairs;
DROP TABLE IF EXISTS widget_url;
CREATE TABLE widget_url
(widget_id INT NOT NULL
,url_id INT NOT NULL
);
INSERT IGNORE INTO widget_url
SELECT DISTINCT w.widget_id
, u.url_id
FROM widget_url_pairs wu
JOIN widgets w
ON w.widget = wu.widget
JOIN urls u
ON u.url = wu.url;
ALTER TABLE widget_url ADD PRIMARY KEY (widget_id,url_id);
SELECT w.widget
, u.url
FROM widgets w
JOIN widget_url wu
ON wu.widget_id = w.widget_id
JOIN urls u
ON u.url_id = wu.url_id;
+---------------+-------------------------------+
| widget | url |
+---------------+-------------------------------+
| blue widget | www.example.com/blue-widgets |
| orange widget | www.example.com/widgets |
| red widget | www.example.com/widgets |
| widget | www.example.com/widgets |
| widget | www.example.com/green-widgets |
+---------------+-------------------------------+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.