[英]MySQL index for normal column and full text column
我正在嘗試加快以下查詢:
我的表有大約400萬條記錄。
EXPLAIN SELECT * FROM chrecords WHERE company_number = 'test' OR MATCH (company_name,registered_office_address_address_line_1,registered_office_address_address_line_2) AGAINST('test') LIMIT 0, 10;
+------+-------------+-----------+------+------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+------------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | chrecords | ALL | i_company_number | NULL | NULL | NULL | 2208348 | Using where |
+------+-------------+-----------+------+------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
我使用以下方法創建了兩個索引:
ALTER TABLE `chapp`.`chrecords` ADD INDEX `i_company_number` (`company_number`);
ALTER TABLE `chapp`.`chrecords`ADD FULLTEXT(
`company_name`,
`registered_office_address_address_line_1`,
`registered_office_address_address_line_2`
);
但是,如何“組合”這兩個索引? 由於上述查詢需要15秒鍾以上的時間才能執行(僅使用一個索引)。
整個表的定義:
CREATE TABLE `chapp`.`chrecords` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`company_name` VARCHAR(100) NULL,
`company_number` VARCHAR(100) NULL,
`registered_office_care_of` VARCHAR(100) NULL,
`registered_office_po_box` VARCHAR(100) NULL,
`registered_office_address_address_line_1` VARCHAR(100) NULL,
`registered_office_address_address_line_2` VARCHAR(100) NULL,
`registered_office_locality` VARCHAR(100) NULL,
`registered_office_region` VARCHAR(100) NULL,
`registered_office_country` VARCHAR(100) NULL,
`registered_office_postal_code` VARCHAR(100) NULL
);
ALTER TABLE `chapp`.`chrecords` ADD INDEX `i_company_name` (`company_name`);
ALTER TABLE `chapp`.`chrecords` ADD INDEX `i_company_number` (`company_number`);
ALTER TABLE `chapp`.`chrecords` ADD INDEX `i_registered_office_address_address_line_1` (`registered_office_address_address_line_1`);
ALTER TABLE `chapp`.`chrecords` ADD INDEX `i_registered_office_address_address_line_2` (`registered_office_address_address_line_2`);
ALTER TABLE `chapp`.`chrecords`ADD FULLTEXT(
`company_name`,
`registered_office_address_address_line_1`,
`registered_office_address_address_line_2`
);
嘗試使用UNION
而不是OR
。
SELECT *
FROM (
SELECT *
FROM chrecords
WHERE company_number = 'test'
) a
UNION (
SELECT *
FROM cbrecords
WHERE MATCH (company_name,
registered_office_address_address_line_1,
registered_office_address_address_line_2)
AGAINST('test')
LIMIT 0, 10
) b
如果這有幫助,那是因為MySQL難以在單個子查詢中使用多個索引。 這給查詢計划者兩個查詢。
您可以分別在每個子查詢上運行EXPLAIN
,以了解其性能。 UNION
只是將其結果放在一起並消除重復項。 如果要保留重復項,請執行UNION ALL
。
請注意,MySQL表上的許多單列索引通常對性能有害。 您應該避免創建索引,除非它們旨在幫助特定查詢。
(
SELECT *
FROM chrecords
WHERE company_number = 'test'
ORDER BY something
LIMIT 10
)
UNION DISTINCT
(
SELECT *
FROM cbrecords
WHERE MATCH (company_name, registered_office_address_address_line_1,
registered_office_address_address_line_2)
AGAINST('test')
ORDER BY something
LIMIT 10
)
ORDER BY something
LIMIT 10
筆記:
SELECT
DISTINCT
(默認設置)或ALL
(更快),這樣您就會知道您是否考慮了去重復,而不是速度。 ORDER BY
LIMIT
的意義不大 ORDER BYs
。 ORDER BY
和LIMIT
,以便您可以正確訂購並限制為10。 如果您需要OFFSET
,則內部需要完整計數,例如5頁LIMIT 50
,n需要跳至第五頁: LIMIT 40,10
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.