我正在寻求帮助设置正确的索引(我已经尝试了太多,现在我有点迷失),正确的MySQL引擎(MyIsam,InnoDB) ...)并帮助我的查询(JOINs,...)。当我认为这些查询应该返回 count(*)。
时,我也很头疼我的时间超过了每次查询5到10秒而不计算,但我不确定我是否可以为这个大数据库获得更好的时间。
我正在尝试优化这个MySQL表:
项目(~600k行):
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| type | varchar(255) | NO | PRI | NULL | |
+-------+------------------+------+-----+---------+----------------+
Items_Relationships(~1M行):
+-------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| lft_item_id | int(11) unsigned | NO | PRI | NULL | |
| rgt_item_id | int(11) unsigned | NO | PRI | NULL | |
| rel_type | varchar(255) | NO | PRI | NULL | |
+-------------+------------------+------+-----+---------+-------+
Items_Values(~4M行):
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| item_id | int(11) unsigned | NO | PRI | 0 | |
| name | varchar(255) | YES | MUL | NULL | |
| value | longtext | YES | | NULL | |
| lang | varchar(2) | YES | | NULL | |
+---------+------------------+------+-----+---------+----------------+
我基本上运行这些常见查询:
1。查询 - 所有值为“status”的项目> 1:
SELECT `company`.`id` AS `id`,
`company`.`type` AS `type`
FROM `items` AS `company`
INNER JOIN `items_values` AS `value_name` ON (`company`.`id` = `value_name`.`item_id`)
WHERE `company`.`type` = 'company'
AND `value_name`.`name` = 'status'
AND CONVERT(`value_name`.`value`, SIGNED) > 1
GROUP BY `company`.`id`
ORDER BY `company`.`id` DESC
LIMIT 0, 30
2。查询 - 包含与其他项目关系的某些值的所有项目:
SELECT `company`.`id` AS `id`,
`company`.`type` AS `type`
FROM `items` AS `company`
INNER JOIN `items_values` AS `value_status` ON (`value_status`.`item_id` = `company`.`id`)
INNER JOIN `items_relationships` AS `companies_categories` ON (`companies_categories`.`lft_item_id` = `company`.`id`)
INNER JOIN `items_values` AS `category_rgt` ON (`category_rgt`.`item_id` = `companies_categories`.`rgt_item_id`)
WHERE `company`.`type` = 'company'
AND `company`.`type` = 'company'
AND `value_status`.`name` = 'status'
AND CONVERT(`value_status`.`value`, SIGNED) >= 1
AND `category_rgt`.`name` = 'rgt'
AND (CONVERT(category_rgt.value, UNSIGNED) BETWEEN 2805 AND 4222)
AND `companies_categories`.`rel_type` = 'company_category'
GROUP BY `company`.`id`
ORDER BY `company`.`id` DESC LIMIT 10
OFFSET 0
提前谢谢!
答案 0 :(得分:0)
如果你询问索引,那么几乎所有你需要的东西都已编入索引。
我刚才有关于
的问题 | name | varchar(255) | YES | MUL | NULL | |
所以我更愿意将它设置为主键。
我只有一个关于表格结构的建议。
如果您的
中有混合字符串和数字 | value | longtext | YES | | NULL | |
创建另一列int_value SIGNED
或无符号甚至更好。
您也应该将该列设置为索引(只要您将该列用作过滤器和/或搜索条件)
并在适用的插入/更新中填写该字段。
此修改将提高查询的性能,您不应在此处使用CAST和/或CONVERT数百万条记录:
AND CONVERT(`value_status`.`value`, SIGNED) >= 1
AND (CONVERT(category_rgt.value, UNSIGNED) BETWEEN 2805 AND 4222)
所以我对结构没有更多的评论。
但是我会请你尝试我的查询,就像实验一样,如果它比你的快。不幸的是,我无法使用任何数据进行调试。如果你提供一些有用的sqlfiddle。
SELECT `company`.`id` AS `id`,
`company`.`type` AS `type`
FROM `items` AS `company`
INNER JOIN (
SELECT
item_id,
FROM items_values
WHERE name = 'status'
AND CONVERT(value, SIGNED) >= 1
) AS value_status
ON value_status.item_id = company.id
INNER JOIN
(
SELECT
lft_item_id
FROM
items_relationships
INNER JOIN (
SELECT
item_id
FROM
items_values
WHERE name = 'rgt'
AND (CONVERT(value, UNSIGNED) BETWEEN 2805 AND 4222)
) AS category_rgt
ON category_rgt.item_id = items_relationships.rgt_item_id
WHERE items_relationships.rel_type = 'company_category'
) as companies_categories
ON (`companies_categories`.`lft_item_id` = `company`.`id`)
WHERE `company`.`type` = 'company'
GROUP BY `company`.`id`
ORDER BY `company`.`id` DESC
LIMIT 10