使用全文索引和其他带有索引的列优化mysql查询

问题描述 投票:0回答:1

我正在对具有100,000+行的表运行以下查询。我试图弄清楚如何使用全文索引,以及如何在与它连接的其他列上使用索引。 (phppos_items的创建表在底部)

SELECT name
FROM `phppos_items`
WHERE (MATCH (phppos_items.name, phppos_items.item_number, product_id, description)
       AGAINST ('"Search* "' IN BOOLEAN MODE)
          or phppos_items.item_id = 'Search')
  and phppos_items.deleted=0 and system_item = 0;

需要0.21秒;可以但它没有完全索引。

这里是解释(如您所见,它检查了58,188行):

mysql> EXPLAIN SELECT name FROM `phppos_items` WHERE (MATCH (phppos_items.name, phppo                                                                          LEAN MODE) or phppos_items.item_id = 'Search') and phppos_items.deleted=0 and system_item = 0;
+----+-------------+--------------+------------+------+-------------------------------------+---------+---------+-------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys                       | key     | key_len | ref   | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+-------------------------------------+---------+---------+-------+-------+----------+-------------+
|  1 | SIMPLE      | phppos_items | NULL       | ref  | PRIMARY,deleted,deleted_system_item | deleted | 4       | const | 58188 |     2.00 | Using where |
+----+-------------+--------------+------------+------+-------------------------------------+---------+---------+-------+-------+----------+-------------+

如果我将查询更改为:

SELECT name
FROM `phppos_items`
WHERE (MATCH (phppos_items.name, phppos_items.item_number, product_id, description) AGAINST ('"Search* "' IN BOOLEAN MODE))

花费0.0005秒并被完全索引。参见说明:

mysql> EXPLAIN SELECT name FROM `phppos_items` WHERE (MATCH (phppos_items.name, phppos_items.item_number, product_id, description) AGAINST ('"Search* "' IN BOOL
+----+-------------+--------------+------------+----------+---------------+-------------+---------+-------+------+----------+-----------------------------------+
| id | select_type | table        | partitions | type     | possible_keys | key         | key_len | ref   | rows | filtered | Extra                             |
+----+-------------+--------------+------------+----------+---------------+-------------+---------+-------+------+----------+-----------------------------------+
|  1 | SIMPLE      | phppos_items | NULL       | fulltext | full_search   | full_search | 0       | const |    1 |   100.00 | Using where; Ft_hints: no_ranking |
+----+-------------+--------------+------------+----------+---------------+-------------+---------+-------+------+----------+-----------------------------------+

这里是创建表:

mysql> show create table phppos_items;
+--------------+---------------------------------------------------------------------+
| Table        | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+--------------+---------------------------------------------------------------------+
| phppos_items | CREATE TABLE `phppos_items` (
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `category_id` int(11) DEFAULT NULL,
  `supplier_id` int(11) DEFAULT NULL,
  `manufacturer_id` int(11) DEFAULT NULL,
  `item_number` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `product_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ecommerce_product_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ecommerce_product_quantity` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `size` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `tax_included` int(1) NOT NULL DEFAULT '0',
  `cost_price` decimal(23,10) NOT NULL,
  `unit_price` decimal(23,10) NOT NULL,
  `promo_price` decimal(23,10) DEFAULT NULL,
  `start_date` date DEFAULT NULL,
  `end_date` date DEFAULT NULL,
  `reorder_level` decimal(23,10) DEFAULT NULL,
  `expire_days` int(10) DEFAULT NULL,
  `item_id` int(10) NOT NULL AUTO_INCREMENT,
  `allow_alt_description` tinyint(1) NOT NULL,
  `is_serialized` tinyint(1) NOT NULL,
  `override_default_tax` int(1) NOT NULL DEFAULT '0',
  `is_ecommerce` int(1) DEFAULT '1',
  `is_service` int(1) NOT NULL DEFAULT '0',
  `is_ebt_item` int(1) NOT NULL DEFAULT '0',
  `commission_percent` decimal(23,10) DEFAULT '0.0000000000',
  `commission_percent_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT '',
  `commission_fixed` decimal(23,10) DEFAULT '0.0000000000',
  `change_cost_price` int(1) NOT NULL DEFAULT '0',
  `disable_loyalty` int(1) NOT NULL DEFAULT '0',
  `deleted` int(1) NOT NULL DEFAULT '0',
  `last_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `ecommerce_last_modified` timestamp NULL DEFAULT NULL,
  `tax_class_id` int(10) DEFAULT NULL,
  `replenish_level` decimal(23,10) DEFAULT NULL,
  `system_item` int(1) NOT NULL DEFAULT '0',
  `max_discount_percent` decimal(15,3) DEFAULT NULL,
  `max_edit_price` decimal(23,10) DEFAULT NULL,
  `min_edit_price` decimal(23,10) DEFAULT NULL,
  `custom_field_1_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_2_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_3_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_4_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_5_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_6_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_7_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_8_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_9_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `custom_field_10_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `required_age` int(10) DEFAULT NULL,
  `verify_age` int(1) NOT NULL DEFAULT '0',
  `weight` decimal(23,10) DEFAULT NULL,
  `length` decimal(23,10) DEFAULT NULL,
  `width` decimal(23,10) DEFAULT NULL,
  `height` decimal(23,10) DEFAULT NULL,
  `ecommerce_shipping_class_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `long_description` longtext COLLATE utf8_unicode_ci NOT NULL,
  `allow_price_override_regardless_of_permissions` int(1) DEFAULT '0',
  `main_image_id` int(10) DEFAULT NULL,
  `only_integer` int(1) NOT NULL DEFAULT '0',
  `is_series_package` int(1) NOT NULL DEFAULT '0',
  `series_quantity` int(10) DEFAULT NULL,
  `series_days_to_use_within` int(10) DEFAULT NULL,
  `is_barcoded` int(1) NOT NULL DEFAULT '1',
  `default_quantity` decimal(23,10) DEFAULT NULL,
  `disable_from_price_rules` int(1) DEFAULT '0',
  `last_edited` timestamp NULL DEFAULT NULL,
  `info_popup` text COLLATE utf8_unicode_ci,
  `item_inactive` int(1) DEFAULT '0',
  PRIMARY KEY (`item_id`),
  UNIQUE KEY `item_number` (`item_number`),
  UNIQUE KEY `product_id` (`product_id`),
  KEY `phppos_items_ibfk_1` (`supplier_id`),
  KEY `deleted` (`deleted`),
  KEY `phppos_items_ibfk_3` (`category_id`),
  KEY `phppos_items_ibfk_4` (`manufacturer_id`),
  KEY `phppos_items_ibfk_5` (`ecommerce_product_id`),
  KEY `description` (`description`(255)),
  KEY `size` (`size`),
  KEY `reorder_level` (`reorder_level`),
  KEY `cost_price` (`cost_price`),
  KEY `unit_price` (`unit_price`),
  KEY `promo_price` (`promo_price`),
  KEY `last_modified` (`last_modified`),
  KEY `name` (`name`),
  KEY `phppos_items_ibfk_6` (`tax_class_id`),
  KEY `deleted_system_item` (`deleted`,`system_item`),
  KEY `custom_field_1_value` (`custom_field_1_value`),
  KEY `custom_field_2_value` (`custom_field_2_value`),
  KEY `custom_field_3_value` (`custom_field_3_value`),
  KEY `custom_field_4_value` (`custom_field_4_value`),
  KEY `custom_field_5_value` (`custom_field_5_value`),
  KEY `custom_field_6_value` (`custom_field_6_value`),
  KEY `custom_field_7_value` (`custom_field_7_value`),
  KEY `custom_field_8_value` (`custom_field_8_value`),
  KEY `custom_field_9_value` (`custom_field_9_value`),
  KEY `custom_field_10_value` (`custom_field_10_value`),
  KEY `verify_age` (`verify_age`),
  KEY `phppos_items_ibfk_7` (`main_image_id`),
  KEY `item_inactive_index` (`item_inactive`),
  FULLTEXT KEY `full_search` (`name`,`item_number`,`product_id`,`description`),
  FULLTEXT KEY `name_search` (`name`),
  FULLTEXT KEY `item_number_search` (`item_number`),
  FULLTEXT KEY `product_id_search` (`product_id`),
  FULLTEXT KEY `description_search` (`description`),
  FULLTEXT KEY `size_search` (`size`),
  FULLTEXT KEY `custom_field_1_value_search` (`custom_field_1_value`),
  FULLTEXT KEY `custom_field_2_value_search` (`custom_field_2_value`),
  FULLTEXT KEY `custom_field_3_value_search` (`custom_field_3_value`),
  FULLTEXT KEY `custom_field_4_value_search` (`custom_field_4_value`),
  FULLTEXT KEY `custom_field_5_value_search` (`custom_field_5_value`),
  FULLTEXT KEY `custom_field_6_value_search` (`custom_field_6_value`),
  FULLTEXT KEY `custom_field_7_value_search` (`custom_field_7_value`),
  FULLTEXT KEY `custom_field_8_value_search` (`custom_field_8_value`),
  FULLTEXT KEY `custom_field_9_value_search` (`custom_field_9_value`),
  FULLTEXT KEY `custom_field_10_value_search` (`custom_field_10_value`),
  CONSTRAINT `phppos_items_ibfk_1` FOREIGN KEY (`supplier_id`) REFERENCES `phppos_suppliers` (`person_id`),
  CONSTRAINT `phppos_items_ibfk_3` FOREIGN KEY (`category_id`) REFERENCES `phppos_categories` (`id`),
  CONSTRAINT `phppos_items_ibfk_4` FOREIGN KEY (`manufacturer_id`) REFERENCES `phppos_manufacturers` (`id`),
  CONSTRAINT `phppos_items_ibfk_6` FOREIGN KEY (`tax_class_id`) REFERENCES `phppos_tax_classes` (`id`),
  CONSTRAINT `phppos_items_ibfk_7` FOREIGN KEY (`main_image_id`) REFERENCES `phppos_item_images` (`image_id`)
) ENGINE=InnoDB AUTO_INCREMENT=20000966 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+--------------+-------------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)
mysql indexing full-text-search
1个回答
0
投票

这里存在严重的数据类型不一致:

`item_id` int(10) NOT NULL AUTO_INCREMENT,
phppos_items.item_id = 'Search'

这特别难以优化:

WHERE (MATCH (phppos_items.name, phppos_items.item_number, product_id, description)
       AGAINST ('"Search* "' IN BOOLEAN MODE)
          or phppos_items.item_id = 'Search')
  and phppos_items.deleted=0
  and system_item = 0;

基本上,执行查询的唯一方法是检查表的每一行。此外,FT测试喜欢“坐在驾驶员座位上”,但这是不允许的。

第一步是摆脱OR

( SELECT ...
    WHERE MATCH(..) AGAINST(..)
      AND phppos_items.deleted=0
      AND system_item = 0 )
UNION DISTINCT
( SELECT ...
    WHERE phppos_items.item_id = 'Search'
      AND phppos_items.deleted=0
      AND system_item = 0 )

第一个SELECT将进行FT测试(非常快),然后根据0测试筛选出任何行。

第二个SELECT将仅使用PRIMARY KEY(item_id)除非有错字!)并检查数字item_id是否为零,并且可能找不到任何行。

然后UNION将收集两个结果集,对其进行消减并非常快速地提供结果。

(将[​​C0]转换为OR是一种通用的优化技术;它对您的查询特别有用。)

我发现在一个表上拥有两个以上的UNIQUE键几乎是不明智的。您确定您有3个吗?

© www.soinside.com 2019 - 2024. All rights reserved.