2015-03-05 2 views
1

Я ищу помощь в настройке правильных индексов (я уже пробовал слишком много, и теперь я немного потерял), правильного движок MySQL (MyISAM, InnoDB .. .) и помогите с моими запросами (JOINs, ...). Также у меня есть головная боль, когда я думаю, что эти запросы должны возвращать count (*).MySQL: Ключ/значение магазина запросы оптимизация

Мое время было более 5 - 10 секунд на запрос без учета, но я не уверен, могу ли я получить лучшие времена для этой большой базы данных.

Я пытаюсь оптимизировать этот MySQL таблицы:

Items (~ 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. запроса - Все элементы со значением "статус"> 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 

Thx заранее!

+1

Магазины с ключевыми знаками, как известно, неудобны для кода и не масштабируются. Вот блог о том, что делать вместо этого. http://mysql.rjweb.org/doc.php/eav –

+0

Посмотрите действительно полезный, но я должен читать его больше раз, чтобы быть ясным. Если у нас есть это решение с примерами, это поможет мне лучше понять .. – Mariyo

ответ

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 
+0

I 'немного улучшенный дизайн 'items_values' путем создания дополнительного столбца' value_index' типа 'int' для предотвращения' CONVERT' и создания нового скомпонованного индекса на 'name и value_index'. Я попробую результат – Mariyo

Смежные вопросы