Mysql
如何添加具有非規範化和 JOINS 的複合 MySQL 索引?
我有以下表格:
CREATE TABLE base_event ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, created_by ... -- some columns ); CREATE TABLE transaction_events ( event_id BIGINT UNSIGNED NOT NULL, transaction_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, merchant_id BIGINT UNSIGNED NULL DEFAULT NULL, merchant_city VARCHAR (...) NULL DEFAULT NULL, -- Denormalize customer_id BIGINT UNSIGNED NULL DEFAULT NULL, customer_ip_address VARCHAR(...) NULL DEFAULT NULL, -- Denormalize ... FOREIGN KEY (event_id) REFERENCES base_event(id), FOREIGN KEY (customer_id) REFERENCES customers(id), FOREIGN KEY (merchant_id) REFERENCES merchants(id), ); CREATE TABLE customers ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, customer_ip_address VARCHAR(...) NULL DEFAULT NULL, ... ); CREATE TABLE merchants ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, ... );
我的
SELECT
:(SELECT t.*, c.name AS customer_name ... FROM transaction_events t JOIN customers c ON t.customer_id = c.id JOIN merchants m ON t.merchant_id = m.id WHERE t.customer_ip_address = 'abc' AND t.transaction_time > 'abc') UNION DISTINCT (SELECT t.*, c.name AS customer_name ... FROM transaction_events t JOIN customers c ON t.customer_id = c.id JOIN merchants m ON t.merchant_id = m.id WHERE t.merchant_city = 'abc' AND t.transaction_time > 'abc')
我的索引是:
ALTER TABLE transaction_events ADD INDEX index_1 (customer_ip_address, transaction_time), ADD INDEX index_2 (merchant_city, transaction_time);
- 我的查詢採用這種形式以避免
OR
.- 為了索引,我已經在一定程度上進行了非規範化。
- 我不需要
base_event
為此查詢引用我的表。- 與
transaction_events
tocustomers
和的關係merchants
不是 1 對 1 而是 1 對 0 或 1。我的問題:
- 我可以擺脫萬用字元,但
transaction_events
有大約 20 列(這有助於創建任何進一步的索引以加快查詢速度嗎?- 我是否需要放置任何其他復合索引(可能引用我的 FK)來進一步改進此查詢?
WHERE
子句指的是,t
因此優化器很可能會以t
每個開頭SELECT
。你有他們的最佳索引。然後它需要進入其他兩個表(
merchants
和customers
)並從中獲取 1(或 0)行。這些表具有 的最佳索引JOIN
,即PRIMARY KEY(id)
在每種情況下。(FK 在此查詢中不起任何作用。)
t.*``TEXT
如果它正在獲取您隨後忽略的大列,則可能會減慢速度。由於您需要所有列,那麼唯一可能的低效率是如果每個
SELECT
都冗餘地獲取同一行,只是被UNION DISTINCT
. 我認為這個問題不值得解決。(解決方法是只進行UNION
查找和重複數據刪除t.id
;然後重新加入t
以獲取其他 19 列。額外工作的成本可能超過收益;我無法確定。)