Intereting Posts
Ошибка в строке 2 в столбце 1: дополнительный контент в конце документа macOS Sierra, устанавливающая расширение PHP Extension Группирование родительских и дочерних категорий для публикации и отображения Сделать правило htaccess применимо только к текущей папке Учетная запись службы Google Диска и «Неавторизованный клиент или область в запросе» Изменение или исключение верхнего колонтитула в TCPDF экономия места в таблице Mysql при включении () или require () мне всегда нужно использовать ../../ относительно моего файла? Есть простой способ? Извлеките все теги text и img из HTML в PHP. Можно ли изменить этот запрос для выполнения двух функций? Как вставить несколько данных в таблицу Сохранение множественного выбора во входном Автоматическое закрытие тегов html и php-тегов в блокноте ++ и точка с запятой в конце строк php Использование href onclick для обновления div без перезагрузки страницы? Как подсчитать СЕССИИ, чтобы отобразить общее количество зарегистрированных пользователей на сайте

MySQL Есть ли ограничение InnerJoin?

У меня есть этот запрос для сбора информации об одном порядке, и он становится довольно сложным.

У меня нет данных для тестирования, поэтому я спрашиваю, есть ли у кого-нибудь опыт работы с этим в небольших и больших наборах данных, существует ли ограничение на количество объединений, которые вы можете или должны сделать в одном запросе? Было бы целесообразно разделить большие запросы на более мелкие части или это не имеет существенного отличия?

Кроме того, законно ли иметь предложение WHERE после каждого INNER JOIN ?

Спасибо за ваш совет.

Вот запрос:

 # Order: Get Order function getOrder($order_id) { $sql = "SELECT (order.id, order.created, o_status.status, /* payment info */ order.total, p_status.status, /* ordered by */ cust_title.title, cust.forename, cust.surname, customer.phone, customer.email, cust.door_name, cust.street1, cust.street2, cust.town, cust.city, cust.postcode, /* deliver to */ recip_title.title, recipient.forename, recipient.surname, recipient.door_name, recipient.street1, recipient.street2, recipient.town, recipient.city, recipient.postcode, /* deliver info */ shipping.name, order.memo, /* meta data */ order.last_update) FROM tbl_order AS order INNER JOIN tbl_order_st AS o_status ON order.order_status_id = o_status.id INNER JOIN tbl_payment_st AS p_status ON order.payment_status_id = p_status.id INNER JOIN (SELECT (cust_title.title, cust.forename, cust.surname, customer.phone, customer.email, /* ordered by */ cust.door_name, cust.street1, cust.street2, cust.town, cust.city, cust.postcode) FROM tbl_customer AS customer INNER JOIN tbl_contact AS cust ON customer.contact_id = cust.id INNER JOIN tbl_contact_title AS cust_title ON cust.contact_title_id = cust_title.id WHERE order.customer_id = customer.id) ON order.customer_id = customer.id INNER JOIN (SELECT (recip_title.title, recipient.forename, recipient.surname, /* deliver to */ recipient.door_name, recipient.street1, recipient.street2, recipient.town, recipient.city, recipient.postcode) FROM tbl_contact AS recipient INNER JOIN tbl_contact_title AS recip_title ON recipient.contact_title_id = recip_title.id WHERE order.contact_id = recipient.id) ON order.contact_id = recipient.id INNER JOIN tbl_shipping_opt AS shipping ON order.shipping_option_id = shipping.id WHERE order.id = '?';"; dbQuery($sql, array((int)$order_id)); $rows = dbRowsAffected(); if ($rows == 1) return dbFetchAll(); else return null; } 

Поскольку кто-то запросил схему для этого запроса, вот он:

 # TBL_CONTACT_TITLE DROP TABLE IF EXISTS tbl_contact_title; CREATE TABLE tbl_contact_title( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), title CHAR(3) ) ENGINE = InnoDB; INSERT INTO tbl_contact_title (title) VALUES ('MR'), ('MRS'), ('MS'); # TBL_CONTACT DROP TABLE IF EXISTS tbl_contact; CREATE TABLE tbl_contact( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), contact_title_id INT, FOREIGN KEY(contact_title_id) REFERENCES tbl_contact_title(id) ON DELETE SET NULL, forename VARCHAR(50), surname VARCHAR(50), door_name VARCHAR(25), street1 VARCHAR(40), street2 VARCHAR(40), town VARCHAR(40), city VARCHAR(40), postcode VARCHAR(10), currency_id INT, FOREIGN KEY(currency_id) REFERENCES tbl_currency(id) ON DELETE SET NULL ) ENGINE = InnoDB; # TBL_CUSTOMER DROP TABLE IF EXISTS tbl_customer; CREATE TABLE tbl_customer( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), contact_id INT, FOREIGN KEY(contact_id) REFERENCES tbl_contact(id) ON DELETE SET NULL, birthday DATE, is_male TINYINT, phone VARCHAR(20), email VARCHAR(50) NOT NULL ) ENGINE = InnoDB, AUTO_INCREMENT = 1000; # TBL_ORDER_ST DROP TABLE IF EXISTS tbl_order_st; CREATE TABLE tbl_order_st( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), status VARCHAR(25) ) ENGINE = InnoDB; INSERT INTO tbl_order_st (status) VALUES ('NEW'), ('PROCESSING'), ('SHIPPED'), ('COMPLETED'), ('CANCELLED'); # TBL_SHIPPING_OPT DROP TABLE IF EXISTS tbl_shipping_opt; CREATE TABLE tbl_shipping_opt( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), name VARCHAR(50), description VARCHAR(255), cost DECIMAL(6,3) ) ENGINE = InnoDB; INSERT INTO tbl_shipping_opt (name, description, cost) VALUES ('UK Premier', 'UK Mainland upto 30KG, Next Working Day', 8.00), ('Europe Standard', 'Most European Destinations* upto 30KG, 2 to 5 Working Days *please check before purchase', 15.00); # TBL_PAYMENT_ST DROP TABLE IF EXISTS tbl_payment_st; CREATE TABLE tbl_payment_st( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), status VARCHAR(25) ) ENGINE = InnoDB; INSERT INTO tbl_payment_st (status) VALUES ('UNPAID'), ('PAID'); # TBL_ORDER DROP TABLE IF EXISTS tbl_order; CREATE TABLE tbl_order( id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), customer_id INT, FOREIGN KEY(customer_id) REFERENCES tbl_customer(id) ON DELETE SET NULL, contact_id INT, FOREIGN KEY(contact_id) REFERENCES tbl_contact(id) ON DELETE SET NULL, created DATETIME, last_update TIMESTAMP, memo VARCHAR(255), order_status_id INT, FOREIGN KEY(order_status_id) REFERENCES tbl_order_st(id), shipping_option_id INT, FOREIGN KEY(shipping_option_id) REFERENCES tbl_shipping_opt(id), coupon_id INT, FOREIGN KEY(coupon_id) REFERENCES tbl_coupon(id) ON DELETE SET NULL, total DECIMAL(9,3), payment_status_id INT, FOREIGN KEY(payment_status_id) REFERENCES tbl_payment_st(id) ) ENGINE = InnoDB, AUTO_INCREMENT = 1000; 

Solutions Collecting From Web of "MySQL Есть ли ограничение InnerJoin?"

У вас нет нигде рядом с лимитом JOINs для MySQL. Количество ваших соединений неплохое. Однако присоединение к производной таблице (ваш внутренний подзапрос), как вы это делаете, может вызвать проблемы с производительностью, поскольку производные таблицы не имеют индексов. Выполнение соединения в производной таблице без индексов может быть медленным.

Вы должны подумать о создании реальной временной таблицы с индексами для присоединения или выяснить способ избежать подзапроса.

JOIN в MySQL в основном похож на поиск (поиск) для каждой объединенной строки. Таким образом, MySQL придется выполнять множество поисковых запросов, если вы присоединяетесь к многим записям. Это меньше о том, сколько таблиц вы присоединяетесь, чем количество строк, к которым вы присоединяетесь, что может быть проблемой.

Во всяком случае, MySQL будет выполнять только столько запросов, прежде чем он сдастся и просто прочитает всю таблицу. Он очень хорошо справляется с решением, которое будет менее дорогостоящим.

Возможно, самое лучшее, что вы можете сделать, это помочь ему угадать, обновив статистику индексов с помощью ANALYZE TABLE.

У вас может быть одно предложение WHERE в SELECT. Таким образом, ваш внутренний подзапрос будет иметь предложение WHERE, и ваш внешний запрос будет иметь предложение WHERE, и они будут применяться после JOIN (по крайней мере, логически, хотя MySQL обычно применит их сначала для производительности).

Кроме того, все это предполагает, что вы знаете, как правильно использовать индексы.

Ну, я однажды попробовал сам увидеть предел для числа подключений, и я протестировал соединение с 100 таблицами в mysql 5.0.4, если я его правильно напомню.

Мне была дана следующая ошибка:

Слишком много таблиц. MySQL может использовать только 61 таблицы в соединении.

Я думаю, что ограничение для MySql 4 составило 31 таблицу.

Если вы планируете использовать столько таблиц в запросе, то пришло время подумать об упрощении дизайна запроса.

Я тоже искал это, и тогда я нашел это другое решение, добавив «AND» как часть JOIN.

 INNER JOIN kopplaMedlemIntresse ON intressen.id = kopplaMedlemIntresse.intresse_id AND kopplaMedlemIntresse.medlem_id = 3 

У меня нет каких-либо общих советов, просто мое собственное выживание.

У меня была некоторая проблема с очень плохой производительностью, когда я добавил тонны таблиц, используя JOIN. Было около 20 штук. Когда я удалил несколько JOINS в тесте, скорость снова поднялась. Из-за того, что мне просто нужна была одна информация, я смог заменить большинство JOINS на подвыборы. Это решило мою проблему с 25 секунд для моего запроса до менее 1 секунды.

Вероятно, это факт вашего дизайна таблицы, количество столбцов соединенных таблиц и ваши индексы на объединенных местах.