powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / оптимизация SQL запроса
25 сообщений из 28, страница 1 из 2
оптимизация SQL запроса
    #39313425
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
запрос

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
SELECT product_id FROM(
SELECT DISTINCT p.product_id, pd.name, p.model, p.quantity, p.price, p.sort_order, p.date_added , p.price as realprice
FROM oc_product p
LEFT JOIN oc_product_option_value pov ON (pov.product_id=p.product_id)
LEFT JOIN oc_product_description pd ON (pd.product_id=p.product_id)
LEFT JOIN oc_product_to_store p2s ON (p2s.product_id=p.product_id)
LEFT JOIN oc_product_to_category p2c ON (p2c.product_id=p.product_id)
LEFT JOIN oc_category_path cp ON(cp.category_id=p2c.category_id)
LEFT JOIN oc_product_attribute p2a ON (p2a.product_id=p.product_id)
LEFT JOIN oc_product_attribute p2a0 ON (p2a0.product_id=p2a.product_id)
LEFT JOIN oc_product_attribute p2a1 ON (p2a1.product_id=p2a.product_id)
LEFT JOIN oc_product_attribute p2a2 ON (p2a2.product_id=p2a.product_id)
LEFT JOIN oc_product_attribute p2a3 ON (p2a3.product_id=p2a.product_id)
LEFT JOIN oc_product_attribute p2a4 ON (p2a4.product_id=p2a.product_id)
LEFT JOIN oc_product_attribute p2a5 ON (p2a5.product_id=p2a.product_id)
WHERE 1 AND cp.path_id IN (3558)
AND p2a0.attribute_id = 12 AND (p2a0.text LIKE '%ЛПО%')
AND p2a1.attribute_id = 20 AND (p2a1.text LIKE '%2х36 Вт%')
AND p2a2.attribute_id = 22 AND (p2a2.text LIKE '%накладные%')
AND p2a3.attribute_id = 27 AND (p2a3.text LIKE '%60 см%')
AND p2a4.attribute_id = 29 AND (p2a4.text LIKE '%T8%')
AND p2a5.attribute_id = 30 AND (p2a5.text LIKE '%220 В%')
AND pd.language_id = '1' AND p.status = '1' AND p2s.store_id = 0) as innertable
WHERE 1 ORDER BY sort_order ASC, LCASE(name) ASC LIMIT 0,20



коллеги, кто сможет оптимизировать этот запрос или предложить альтернативный более быстрый вариант?
сейчас данный запрос выполняется 37секунд
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313472
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011,

Показывайте план этого кошмара.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313473
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011кто сможет оптимизировать этот запросВсе LEFT JOIN, для которых Вы не сможете ДОКАЗАТЬ необходимость именно LEFT, заменить на INNER JOIN.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313475
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И для этих связей условия отбора попробовать перенести из WHERE в ON. Причём каждый перенос рассматривать отдельно.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313480
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaВсе LEFT JOIN, для которых Вы не сможете ДОКАЗАТЬ необходимость именно LEFT, заменить на INNER JOIN.В текущем виде запроса, если не ошибаюсь, все LEFT JOIN можно заменить на JOIN.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313481
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
Детальный профиль
Порядок сортировки
	СостояниеДокументация
	Время
1 	Starting 	35 µs
2 	Waiting For Query Cache Lock 	4 µs
3 	Checking Query Cache For Query 	249 µs
4 	Checking Permissions 	8 µs
5 	Checking Permissions 	3 µs
6 	Checking Permissions 	3 µs
7 	Checking Permissions 	3 µs
8 	Checking Permissions 	3 µs
9 	Checking Permissions 	2 µs
10 	Checking Permissions 	3 µs
11 	Checking Permissions 	2 µs
12 	Checking Permissions 	3 µs
13 	Checking Permissions 	3 µs
14 	Checking Permissions 	3 µs
15 	Checking Permissions 	3 µs
16 	Checking Permissions 	4 µs
17 	Opening Tables 	119 µs
18 	After Opening Tables 	14 µs
19 	System Lock 	30 µs
20 	Table Lock 	13 µs
21 	After Table Lock 	13 µs
22 	Waiting For Query Cache Lock 	4 µs
23 	After Table Lock 	70 µs
24 	Init 	192 µs
25 	Optimizing 	8 µs
26 	Optimizing 	109 µs
27 	Statistics 	35.7 s
28 	Preparing 	521 µs
29 	Statistics 	32 µs
30 	Preparing 	17 µs
31 	Executing 	11 µs
32 	Sorting Result 	66 µs
33 	Executing 	5 µs
34 	Creating Tmp Table 	122 µs
35 	Copying To Tmp Table 	39.3 ms
36 	Sending Data 	46 µs
37 	Removing Tmp Table 	19 µs
38 	Sending Data 	81 µs
39 	Sending Data 	92 µs
40 	End 	24 µs
41 	Query End 	25 µs
42 	Closing Tables 	6 µs
43 	Removing Tmp Table 	8 µs
44 	Closing Tables 	112 µs
45 	Freeing Items 	46 µs
46 	Updating Status 	17 µs
47 	Waiting For Query Cache Lock 	5 µs
48 	Updating Status 	1.4 ms
49 	Waiting For Query Cache Lock 	7 µs
50 	Updating Status 	2 µs
51 	Storing Result In Query Cache 	9 µs
52 	Logging Slow Query 	9 µs
53 	Cleaning Up 	21 µs
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313483
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как видно п 27 Statistics 35.7 s
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313485
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011
Код: plaintext
27 	Statistics 	35.7 s
Чудны дела MySQL-евских потрохов...

Но это все равно не то, нужен именно план. Добавьте слово EXPLAIN в начале запроса и выполните.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313487
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
этот чудо запрос формируется внедрах модуля FilterPro опенкарт :)
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313488
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011этот чудо запрос формируется внедрах модуля FilterPro опенкарт :)Тогда рассказывайте, какие телодвижения вообще возможны?
Переписывать запрос одновременно с перепроектированием базы, как я понимаю, уже можно не предлагать?
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313491
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
при замене всех LEFT на INNER "MySQL вернула пустой результат (т.е. ноль строк). (Запрос занял 44.7335 сек.)"
т.е. мало того что работает не правильно так еще и дольше))

это с explain
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313498
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
для запроса с простыми JOIN время 45сек
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313501
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011,

Строку "LEFT JOIN oc_product_option_value pov ON (pov.product_id=p.product_id)" либо оставьте как есть, либо выкиньте вообще, т.к. эта таблица не используется больше ни для чего. В таблице oc_product_option_value нет записей и переход от LEFT JOIN к JOIN приводит к пустому результату.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313505
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftphpcoder2011этот чудо запрос формируется внедрах модуля FilterPro опенкарт :)Тогда рассказывайте, какие телодвижения вообще возможны?
Переписывать запрос одновременно с перепроектированием базы, как я понимаю, уже можно не предлагать?

сложно сказать, думаю очень ограничены, дело в том что этот запрос портянка формируется другой рнр портянкой
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
    public function getProducts($data) {
        $customer_group_id = $this->getCustomerGroup();

        $sql = "SELECT product_id FROM(";
        $sql .= "SELECT DISTINCT p.product_id, pd.name, p.model, p.quantity, p.price, p.sort_order, p.date_added ";
        if(isset($data["sort"]) && $data["sort"] == "rating") {
            $sql .= ", (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating ";
        }
        $sql .= ", p.price as realprice ";
        $sql .= "FROM " . DB_PREFIX . "product p" .
            " LEFT JOIN " . DB_PREFIX . "product_option_value pov ON (pov.product_id=p.product_id)" .
            " LEFT JOIN " . DB_PREFIX . "product_description pd ON (pd.product_id=p.product_id)" .
            " LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p2s.product_id=p.product_id)" .
            " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p2c.product_id=p.product_id)";
        if (!empty($data['sub_categories']) || !empty($data['filter_sub_category'])) {
            $sql .= " LEFT JOIN " . DB_PREFIX . "category_path cp ON(cp.category_id=p2c.category_id) ";
        }
        if(!empty($data['attribute_value']) || !empty($data['attr_slider'])) {
            $sql .= " LEFT JOIN " . DB_PREFIX . "product_attribute p2a ON (p2a.product_id=p.product_id)";
        }

        if(!empty($data['tags'])) {
            $sql .= " LEFT JOIN " . DB_PREFIX . "product_tag p2t ON (p2t.product_id=p.product_id)";
        }

        if(!empty($data['attribute_value']) && (empty($this->filterpro_setting) || $this->filterpro_setting['attribute_mode'] == 'and')) {
            $i = 0;

            foreach($data['attribute_value'] as $attribute_id => $values) {
                $sql .= " LEFT JOIN " . DB_PREFIX . "product_attribute p2a" . $i . " ON (p2a" . $i . ".product_id=p2a.product_id)";
                $i++;
            }
        }

        $sql .= " WHERE 1";

        if(!empty($data['instock'])) {
            $sql .= " AND p.quantity > 0 AND (pov.quantity is null OR pov.quantity > 0)";
        }

        if (empty($data['categories']) && !empty($data['filter_category_id'])) {
            $data['categories'][] = $data['filter_category_id'];
        }
        if($data['categories']) {
            if (empty($data['sub_categories']) && empty($data['filter_sub_category'])) {
                $sql .= " AND p2c.category_id IN (" . implode(",", $data['categories']) . ")";
            } else {
                $sql .= " AND cp.path_id IN (" . implode(",", $data['categories']) . ")";
            }
        }

        $option_filters = array();
        if(!empty($data['option_value'])) {
            foreach($data['option_value'] as $option_value) {
                $option_filters[] = "option_value_id IN(" . implode(",", $option_value) . ")";
            }
        }

        if($option_filters) {
            if(empty($this->filterpro_setting) || $this->filterpro_setting['option_mode'] == 'and') {
                foreach($option_filters as $i => $option_filter) {
                    $sql .= " AND EXISTS (select 1 FROM " . DB_PREFIX . "product_option_value pov" . $i .
                        " WHERE pov" . $i . ".product_id=pov.product_id AND pov" . $i . "." . $option_filter . ($data['instock'] ? "AND pov" . $i . ".quantity > 0"
                            : "") . ") ";
                }
            } else {
                $sql .= " AND (" . implode(" OR ", $option_filters) . ")";
            }
        }

        if(!empty($data['manufacturer'])) {
            $sql .= " AND p.manufacturer_id IN(" . implode(", ", $data['manufacturer']) . ")";
        }

        if(!empty($data['tags'])) {
            $sql .= " AND p2t.tag IN( '" . implode("', '", array_map(array($this->db, 'escape'), $data['tags'])) . "') AND p2t.language_id='" . (int)$this->config->get('config_language_id') . "' ";
        }

        $d = $this->filterpro_setting['attr_delimeter'];

        if(!empty($data['attribute_value'])) {
            if(empty($this->filterpro_setting) || $this->filterpro_setting['attribute_mode'] == 'and') {
                $i = 0;

                foreach($data['attribute_value'] as $attribute_id => $values) {
                    if(empty($this->filterpro_setting) || $this->filterpro_setting['attribute_value_mode'] == 'or') {

                        $sql .= " AND p2a" . $i . ".attribute_id = " . (int)$attribute_id .
                            " AND (p2a" . $i . ".text LIKE '%" . implode("%' OR p2a" . $i . ".text LIKE '%", array_map(array($this->db, 'escape'), $values)) . "%')";

                        $i++;
                    } else {
                        foreach($values as $value) {
                            $sql .= " AND  p2a" . $i . ".attribute_id = " . (int)$attribute_id .
                                " AND p2a" . $i . ".text = '" . $this->db->escape($value) . "'";
                            $i++;
                        }
                    }
                }
            } else {
                foreach($data['attribute_value'] as $attribute_id => $values) {
                    $attribute_filters[] = "p2a.attribute_id = " . (int)$attribute_id .
                        " AND (p2a.text = '" . implode("' OR p2a.text = '", array_map(array($this->db, 'escape'), $values)) . "'" .
                        ")";
                    /*										   " OR p2a.text like '" . implode($d . "%' OR p2a.text like '", array_map(array($this->db, 'escape'), $values)) . $d . "%'" .
                                                               " OR p2a.text like '%" . $d . implode("' OR p2a.text like '%" . $d, array_map(array($this->db, 'escape'), $values)) . "'" .
                                                               " OR p2a.text like '%" . $d . implode($d . "%' OR p2a.text like '%" . $d, array_map(array($this->db, 'escape'), $values)) . $d . "%')";*/
                }
                $sql .= " AND (" . implode(" OR ", $attribute_filters) . ")";
            }
        }

        if(!empty($data['attr_slider'])) {
            $i = 0;
            foreach($data['attr_slider'] as $attribute_id => $values) {
                if(!isset($values['min'])) {
                    $sql .= " AND EXISTS (select 1 FROM " . DB_PREFIX . "product_attribute p2a" . $i . " WHERE p2a" . $i . ".product_id = p2a.product_id AND p2a" . $i . ".attribute_id = " . (int)$attribute_id . " AND " .
                        "(p2a" . $i . ".text * 1 <= " . $values['max'] . ")) ";
                } elseif(!isset($values['max'])) {
                    $sql .= " AND EXISTS (select 1 FROM " . DB_PREFIX . "product_attribute p2a" . $i . " WHERE p2a" . $i . ".product_id = p2a.product_id AND p2a" . $i . ".attribute_id = " . (int)$attribute_id . " AND " .
                        "(p2a" . $i . ".text * 1 >= " . $values['min'] . ")) ";

                } else {
                    $sql .= " AND EXISTS (select 1 FROM " . DB_PREFIX . "product_attribute p2a" . $i . " WHERE p2a" . $i . ".product_id = p2a.product_id AND p2a" . $i . ".attribute_id = " . (int)$attribute_id . " AND " .
                        "(p2a" . $i . ".text * 1 BETWEEN " . $values['min'] . " AND " . $values['max'] . ")) ";
                }
                $i++;
            }
        }

        if(!empty($data['min_price']) && $data['min_price'] >= 0) {
            $min_price = $this->currency->convert((int)$data['min_price'], $this->currency->getCode(), $this->config->get('config_currency'));
            $sql .= " AND p.price >=" . (int)($min_price);
        }

        $sql .= " AND pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p2s.store_id = " . (int)$this->config->get('config_store_id');

        $sort_data = array(
            'pd.name' => 'name',
            'p.model' => 'model',
            'p.quantity' => 'quantity',
            'p.price' => 'realprice',
            'p.sort_order' => 'sort_order',
            'p.date_added' => 'date_added',
            'rating' => 'rating'
        );

        $sql .= ") as innertable WHERE 1 ";
        if(!empty($data['min_price']) && $data['min_price']>= 0) {
            $min_price = $this->currency->convert((int)$data['min_price'], $this->currency->getCode(), $this->config->get('config_currency'));
            $sql .= "AND realprice >=" . (int)($min_price);
        }
        if(!empty($data['max_price']) && $data['max_price']> 0) {
            $max_price = $this->currency->convert($data['max_price'], $this->currency->getCode(), $this->config->get('config_currency'));
            $sql .= " AND realprice <=" . ($max_price);
        }

        if(isset($data['sort']) && array_key_exists($data['sort'], $sort_data)) {
            $data['sort'] = $sort_data[$data['sort']];
            if($data['sort'] == 'name' || $data['sort'] == 'model') {
                $sql .= " ORDER BY LCASE(" . $data['sort'] . ")";
            } elseif ($data['sort'] == 'realprice') {
                $sql .= " ORDER BY (realprice<>0) DESC, realprice";
            } else {
                $sql .= " ORDER BY " . $data['sort'];
            }
        } else {
            $sql .= " ORDER BY  sort_order";
        }
        if(isset($data['order']) && ($data['order'] == 'DESC')) {
            $sql .= " DESC, LCASE(name) DESC";
        } else {
            $sql .= " ASC, LCASE(name) ASC";
        }


        if(isset($data['start']) || isset($data['limit'])) {
            if($data['start'] < 0) {
                $data['start'] = 0;
            }

            if($data['limit'] < 1) {
                $data['limit'] = 20;
            }

            $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
        }

        $query = $this->db->query($sql);
//		var_dump($sql);
        $product_data = array();
        if($query->rows) {
            $this->load->model('catalog/product');
            foreach($query->rows as $result) {
                $product_data[$result['product_id']] = $this->model_catalog_product->getProduct($result['product_id']);
            }
        }
        return $product_data;
    }

...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313514
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftphpcoder2011,

Строку "LEFT JOIN oc_product_option_value pov ON (pov.product_id=p.product_id)" либо оставьте как есть, либо выкиньте вообще, т.к. эта таблица не используется больше ни для чего. В таблице oc_product_option_value нет записей и переход от LEFT JOIN к JOIN приводит к пустому результату.

да, я рассматривал и этот вариант (с выкидыванием ненужных таблиц, а также выкидыванием ненужных столбцов), но если посмотреть рнр портянку, то станет понятно, что она все такие иногда используется
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313516
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011miksoftphpcoder2011,

Строку "LEFT JOIN oc_product_option_value pov ON (pov.product_id=p.product_id)" либо оставьте как есть, либо выкиньте вообще, т.к. эта таблица не используется больше ни для чего. В таблице oc_product_option_value нет записей и переход от LEFT JOIN к JOIN приводит к пустому результату.

да, я рассматривал и этот вариант (с выкидыванием ненужных таблиц, а также выкидыванием ненужных столбцов), но если посмотреть рнр портянку, то станет понятно, что она все такие иногда используетсяТогда оставьте LEFT JOIN для нее. MySQL сам успешно выкидывает ее из запроса. Хотя что толку использовать пустую таблицу...
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313523
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011,

И попробуйте сделать OPTIMIZE TABLE для всех таблиц в запросе. Возможно, это облегчит жизнь оптимизатору.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313714
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а по explain'ну получается mysql каждый джойн рассматривает как отдельный запрос, и уже потом делает объединение?
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313750
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011по explain'ну получается mysql каждый джойн рассматривает как отдельный запрос, и уже потом делает объединение?Нет. Каждая таблица отдельно готовится для использования в запросе. С учётом её наполнения, статистики, типа связи и использованных условий отбора и связывания.
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313760
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftphpcoder2011,

И попробуйте сделать OPTIMIZE TABLE для всех таблиц в запросе. Возможно, это облегчит жизнь оптимизатору.

вы будете смеяться, но это реально помогло :)
на двух серверах результат одинаково положительный
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39313766
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
phpcoder2011miksoftphpcoder2011,

И попробуйте сделать OPTIMIZE TABLE для всех таблиц в запросе. Возможно, это облегчит жизнь оптимизатору.

вы будете смеяться, но это реально помогло :)
на двух серверах результат одинаково положительныйНасколько положительный? :)
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39314610
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft,

ну вместо 37секунд меньше теперь время выполнения меньше 1 секунды
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39314619
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я так понимаю БД никогда не оптимизировалась, а вот операции модификации совершались регулярно и видимо одна из таблиц обросла мхом) какая именно таблица тормозила весь процесс сейчас уже не выяснить, могу сказать только что я пробовал выкинуть из запроса все что только можно:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT product_id FROM(
SELECT DISTINCT p.product_id, pd.name, p.sort_order
FROM oc_product p 
LEFT JOIN oc_product_description pd ON (pd.product_id=p.product_id) 
LEFT JOIN oc_product_to_store p2s ON (p2s.product_id=p.product_id) 
LEFT JOIN oc_product_to_category p2c ON (p2c.product_id=p.product_id) 
LEFT JOIN oc_category_path cp ON(cp.category_id=p2c.category_id)  
LEFT JOIN oc_product_attribute p2a0 ON (p2a0.product_id=p.product_id) 
LEFT JOIN oc_product_attribute p2a1 ON (p2a1.product_id=p.product_id) 
LEFT JOIN oc_product_attribute p2a2 ON (p2a2.product_id=p.product_id) 
LEFT JOIN oc_product_attribute p2a3 ON (p2a3.product_id=p.product_id) 
LEFT JOIN oc_product_attribute p2a4 ON (p2a4.product_id=p.product_id) 
LEFT JOIN oc_product_attribute p2a5 ON (p2a5.product_id=p.product_id) 
WHERE 1 AND cp.path_id IN (3558) 
AND p2a0.attribute_id = 12 AND (p2a0.text LIKE '%ЛПО%') 
AND p2a1.attribute_id = 20 AND (p2a1.text LIKE '%2х36 Вт%') 
AND p2a2.attribute_id = 22 AND (p2a2.text LIKE '%накладные%') 
AND p2a3.attribute_id = 27 AND (p2a3.text LIKE '%60 см%') 
AND p2a4.attribute_id = 29 AND (p2a4.text LIKE '%T8%') 
AND p2a5.attribute_id = 30 AND (p2a5.text LIKE '%220 В%') 
AND pd.language_id = '1' AND p.status = '1' AND p2s.store_id = 0) as innertable 
WHERE 1  ORDER BY sort_order ASC, LCASE(name) ASC LIMIT 0,20



и в таком виде он выполнялся 3+сек до оптимизации таблиц.
сейчас же даже без модификации запроса время выполнения менее 0,02сек
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39314627
phpcoder2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
еще был эксперимент: создана таблица oc_product_attribute2 аналог oc_product_attribute, только в ней на 50% больше строк
дело в том что поле text содержит название атрибутов и иногда атрибуты составные (через двоеточие) например ЛПО:220В, вот эти составные атрибуты разбиты на отдельные строки
собственно проверялось предположение о тормозах лайков
запроса вида:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT product_id FROM(
SELECT DISTINCT p.product_id, pd.name, p.sort_order
FROM oc_product p 
LEFT JOIN oc_product_description pd ON (pd.product_id=p.product_id) 
LEFT JOIN oc_product_to_store p2s ON (p2s.product_id=p.product_id) 
LEFT JOIN oc_product_to_category p2c ON (p2c.product_id=p.product_id) 
LEFT JOIN oc_category_path cp ON(cp.category_id=p2c.category_id)  
LEFT JOIN oc_product_attribute2 p2a0 ON (p2a0.product_id=p.product_id) 
LEFT JOIN oc_product_attribute2 p2a1 ON (p2a1.product_id=p.product_id) 
LEFT JOIN oc_product_attribute2 p2a2 ON (p2a2.product_id=p.product_id) 
LEFT JOIN oc_product_attribute2 p2a3 ON (p2a3.product_id=p.product_id) 
LEFT JOIN oc_product_attribute2 p2a4 ON (p2a4.product_id=p.product_id) 
LEFT JOIN oc_product_attribute2 p2a5 ON (p2a5.product_id=p.product_id) 
WHERE 1 AND cp.path_id IN (3558) 
AND p2a0.attribute_id = 12 AND (p2a0.text = 'ЛПО') 
AND p2a1.attribute_id = 20 AND (p2a1.text = '2х36 Вт') 
AND p2a2.attribute_id = 22 AND (p2a2.text = 'накладные') 
AND p2a3.attribute_id = 27 AND (p2a3.text = '60 см') 
AND p2a4.attribute_id = 29 AND (p2a4.text = 'T8') 
AND p2a5.attribute_id = 30 AND (p2a5.text = '220 В') 
AND pd.language_id = '1' AND p.status = '1' AND p2s.store_id = 0) as innertable 
WHERE 1  ORDER BY sort_order ASC, LCASE(name) ASC LIMIT 0,20


теперь выполняется за 0.1042 сек (что в разы медленнее по сравнению с оригиналом), а раньше (до оптимизации таблиц) разницы не было
...
Рейтинг: 0 / 0
оптимизация SQL запроса
    #39314628
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И тем не менее я бы предложил всё же привести в соответствие логику и текст запроса. Это про замену левых связываний на внутренние.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
SELECT product_id 
FROM
(
SELECT DISTINCT p.product_id, pd.name, p.sort_order
FROM oc_product p 
INNER JOIN oc_product_description pd ON (pd.product_id=p.product_id) 
INNER JOIN oc_product_to_store p2s ON (p2s.product_id=p.product_id) 
/* а эту строку бы выбросить */ LEFT JOIN oc_product_to_category p2c ON (p2c.product_id=p.product_id) 
INNER JOIN oc_category_path cp ON(cp.category_id=p2c.category_id)  
INNER JOIN oc_product_attribute p2a0 ON (p2a0.product_id=p.product_id) 
INNER JOIN oc_product_attribute p2a1 ON (p2a1.product_id=p.product_id) 
INNER JOIN oc_product_attribute p2a2 ON (p2a2.product_id=p.product_id) 
INNER JOIN oc_product_attribute p2a3 ON (p2a3.product_id=p.product_id) 
INNER JOIN oc_product_attribute p2a4 ON (p2a4.product_id=p.product_id) 
INNER JOIN oc_product_attribute p2a5 ON (p2a5.product_id=p.product_id) 
WHERE 1 
AND cp.path_id IN (3558) 
AND p2a0.attribute_id = 12 AND (p2a0.text LIKE '%ЛПО%') 
AND p2a1.attribute_id = 20 AND (p2a1.text LIKE '%2х36 Вт%') 
AND p2a2.attribute_id = 22 AND (p2a2.text LIKE '%накладные%') 
AND p2a3.attribute_id = 27 AND (p2a3.text LIKE '%60 см%') 
AND p2a4.attribute_id = 29 AND (p2a4.text LIKE '%T8%') 
AND p2a5.attribute_id = 30 AND (p2a5.text LIKE '%220 В%') 
AND pd.language_id = '1' -- а нафига кавычки?
AND p.status =       '1' -- и тут тоже?
AND p2s.store_id = 0
) as innertable 
WHERE 1  
ORDER BY sort_order ASC, LCASE(name) ASC 
LIMIT 0,20


Зачем заставлять сервер делать лишнюю работу?
...
Рейтинг: 0 / 0
25 сообщений из 28, страница 1 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / оптимизация SQL запроса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]