Hundreds of indexes created automatically - sql

I created a table which is used for storing information relative to resources of different kind, the table description prints 250 indexes for each foreign key, is this behavior normal?
The table contains only 50 rows.
CREATE TABLE IF NOT EXISTS resource
(
id serial PRIMARY KEY,
kind resource_kind NOT NULL,
author_id int REFERENCES user(id) ON DELETE SET NULL,
---uri text NOT NULL,
creation_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
modification_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
message_id int references message,
track_id int references track,
location_id int references track,
fileupload_id int references upload
check (
(
(message_id is not null)::integer +
(track_id is not null)::integer +
(location_id is not null)::integer +
(fileupload_id is not null)::integer
) = 1
)
);
create unique index on resource (message_id) where message_id is not null;
create unique index on resource (track_id) where track_id is not null;
create unique index on resource (location_id) where location_id is not null;
create unique index on resource (fileupload_id) where fileupload_id is not null;
And this is the output of "\d resource"
Colonna | Tipo | Ordinamento | | Default
-------------------+-----------------------------+-------------+-----------------+------------------------------------------------
id | integer | | not null | nextval('resource_id_seq'::regclass)
kind | resource_kind | | not null |
author_id | integer | | |
creation_time | timestamp without time zone | | not null | CURRENT_TIMESTAMP
modification_time | timestamp without time zone | | not null | CURRENT_TIMESTAMP
message_id | integer | | |
track_id | integer | | |
location_id | integer | | |
fileupload_id | integer | | |
Indici:
"resource_pkey" PRIMARY KEY, btree (id)
"resource_fileupload_id_idx" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx1" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx10" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx100" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx101" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx102" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx103" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx104" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx105" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx106" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
"resource_fileupload_id_idx107" UNIQUE, btree (fileupload_id) WHERE fileupload_id IS NOT NULL
...
And then the outputs goes with hundreds of indexes for each foreign key.

No, that is not normal.
Somebody or some software must have created the indexes.
Remove them all except for one, because they use space and will make data modifications unbearably slow.

Next time you could put all the constraints inside the DDL for the table, making it conditional on NOT EXISTS (this will also create unique names for the indexes) :
CREATE TABLE IF NOT EXISTS resource
(
id serial PRIMARY KEY
, kind INTEGER NOT NULL -- resource_kind NOT NULL
, author_id INTEGER -- REFERENCES user(id) ON DELETE SET NULL
-- , uri text NOT NULL
, creation_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
, modification_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
, message_id INTEGER -- references message
, track_id INTEGER -- references track
, location_id INTEGER -- references track
, fileupload_id INTEGER -- references upload
, unique (message_id)
, unique (track_id)
, unique (location_id)
, unique (fileupload_id)
, check (
(
(message_id is not null)::integer
+ (track_id is not null)::integer
+ (location_id is not null)::integer
+ (fileupload_id is not null)::integer
) = 1
)
);
-- check it
\d resource

Related

How do I calculate the revenue earned per person and per year

I suppose it is quite simple, I just can't get the hang of it.
At the moment I have the following code:
SELECT s.first_name, s.last_name, s.staff_id, SUM(p.amount) AS 'Revenue'
FROM payment p
JOIN staff s
ON s.staff_id = p.staff_id
GROUP BY s.staff_id
This gives me the 2 staff members and their revenue but I'm still missing the yearly part.
I'm yet again using the sakila database, if anybody could help me I would really appreciate it, thanks in regards
Edit for the tables:
-- sakila.staff definition
CREATE TABLE `staff` (
`staff_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`address_id` smallint(5) unsigned NOT NULL,
`picture` blob DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`store_id` tinyint(3) unsigned NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT 1,
`username` varchar(16) NOT NULL,
`password` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`staff_id`),
KEY `idx_fk_store_id` (`store_id`),
KEY `idx_fk_address_id` (`address_id`),
CONSTRAINT `fk_staff_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`) ON UPDATE CASCADE,
CONSTRAINT `fk_staff_store` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `payment` (
`payment_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`customer_id` smallint(5) unsigned NOT NULL,
`staff_id` tinyint(3) unsigned NOT NULL,
`rental_id` int(11) DEFAULT NULL,
`amount` decimal(5,2) NOT NULL,
`payment_date` datetime NOT NULL,
`last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`payment_id`),
KEY `idx_fk_staff_id` (`staff_id`),
KEY `idx_fk_customer_id` (`customer_id`),
KEY `fk_payment_rental` (`rental_id`),
CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE,
CONSTRAINT `fk_payment_rental` FOREIGN KEY (`rental_id`) REFERENCES `rental` (`rental_id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `fk_payment_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`staff_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=16050 DEFAULT CHARSET=utf8mb4;
This can be done by simply adding the year to the GROUP BY clause, like this:
SELECT s.first_name, s.last_name, s.staff_id, SUM(p.amount) AS 'Revenue'
, YEAR(payment_date) AS year
FROM payment p
JOIN staff s
ON s.staff_id = p.staff_id
GROUP BY s.staff_id, year
;
This means, generate a SUM for each group associated with rows having the same (staff_id, year) pairs.
The result:
+------------+-----------+----------+----------+------+
| first_name | last_name | staff_id | Revenue | year |
+------------+-----------+----------+----------+------+
| Mike | Hillyer | 1 | 33255.38 | 2005 |
| Mike | Hillyer | 1 | 234.09 | 2006 |
| Jon | Stephens | 2 | 33646.95 | 2005 |
| Jon | Stephens | 2 | 280.09 | 2006 |
+------------+-----------+----------+----------+------+

SQL - database references

Sales table:
id | product_id | year | quantity | price
---+------------+------+----------+-------
1 | 100 | 2008 | 10 | 5000
2 | 100 | 2008 | 10 | 5000
3 | 200 | 2011 | 15 | 9000
Products table:
id | product_name | product_id
---+--------------+------------
1 | Nokia | 100
2 | Apple | 200
3 | Samsung | 200
In these two tables, I have references the Sales table and the Products table as shown here:
CREATE TABLE Sales_table
(
id SERIAL PRIMARY KEY,
product_id INTEGER NOT NULL,
year INTEGER NOT NULL,
quantity INTEGER NOT NULL,
price INTEGER NOT NULL
);
CREATE TABLE Products_table
(
id SERIAL PRIMARY KEY,
product_name VARCHAR NOT NULL,
product_id INTEGER REFERENCES Sales_table
);
These two tables are created successfully, but when I insert data into the Products_table, I get an error
ERROR: insert or update on table "products_table" violates foreign key constraint "products_table_product_id_fkey"
DETAIL: Key (product_id)=(200) is not present in table "sales_table".
By the mean of, the referenced table doesn't allow same 'product_id' field name means, then why the Products_table table has been created with the REFERENCES of Sales_table?
Your foreign key references are backwards. You want:
CREATE TABLE Products_table (
id SERIAL PRIMARY KEY,
product_name VARCHAR NOT NULL
);
CREATE TABLE Sales_table (
id SERIAL PRIMARY KEY,
product_id INTEGER NOT NULL,
year INTEGER NOT NULL,
quantity INTEGER NOT NULL,
price INTEGER NOT NULL,
product_id INTEGER REFERENCES product_table (id)
);
I actually advise naming the primary key after the table -- so primary key and foreign key column names match (i.e. JOINs with USING make sense). Also, in more recent versions of Postgres, generated always as identity is preferred over serial. So:
CREATE TABLE Products_table (
product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
product_name VARCHAR NOT NULL
);
CREATE TABLE Sales_table (
sale_id GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
product_id INTEGER NOT NULL,
year INTEGER NOT NULL,
quantity INTEGER NOT NULL,
price INTEGER NOT NULL,
product_id INTEGER REFERENCES products_table (product_id)
);

how to create inheritance table in oracle

there is table called event that act as parent the child inherit tables of event are special event and hotel event i have created the types as bellow but I'm contuse about how to create tables to these tables in oracle.I have referred most of the currently available solutions within Stack overflow, git hub etc. However, none of these solutions have worked out successfully.
Table types :
Event_t (
EventID:char(5),
EventType:varchar(20),
VenueName:varchar(50),
NoOfGuest:number(10)
) NOT FINAL
HotelEvent_t (
Date:date,
Price:numbr(8,2)
) UNDER Event_t
SpecialEvent_t (
BookingDate:date,
EndDate:date,
MenuNumber:number(2),
Reservation ref Reservation_t
) UNDER event_t
Thank you very much and any suggestion will be greatly appreciated.
Create your types using the correct syntax:
CREATE TYPE Event_t AS OBJECT(
EventID char(5),
EventType varchar(20),
VenueName varchar(50),
NoOfGuest number(10)
) NOT FINAL;
CREATE TYPE HotelEvent_t UNDER Event_t (
datetime date, -- Date is a keyword, try to use a different name.
Price number(8,2)
);
CREATE TYPE SpecialEvent_t UNDER event_t (
BookingDate date,
EndDate date,
MenuNumbers NUMBER(2),
Reservation ref Reservation_t
);
Then you can create an object table:
CREATE TABLE Events OF Event_T(
eventid CONSTRAINT Events__EventID__PK PRIMARY KEY
);
Then you can insert the different types into it:
INSERT INTO EVENTS VALUES(
HotelEvent_T(
'H1',
'HOTEL',
'Venue1',
42,
DATE '0001-02-03' + INTERVAL '04:05:06' HOUR TO SECOND,
123456.78
)
);
INSERT INTO EVENTS VALUES(
SpecialEvent_T(
'SE1',
'SPECIAL',
'Time Travel Convention',
-1,
SYSDATE,
TRUNC(SYSDATE),
0,
NULL
)
);
and get the data out of it:
SELECT e.*,
TREAT( VALUE(e) AS HotelEvent_T ).datetime AS datetime,
TREAT( VALUE(e) AS HotelEvent_T ).price AS price,
TREAT( VALUE(e) AS SpecialEvent_T ).bookingdate AS bookingdate,
TREAT( VALUE(e) AS SpecialEvent_T ).enddate AS enddate,
TREAT( VALUE(e) AS SpecialEvent_T ).menunumbers AS menunumbers
FROM Events e;
Which outputs:
EVENTID | EVENTTYPE | VENUENAME | NOOFGUEST | DATETIME | PRICE | BOOKINGDATE | ENDDATE | MENUNUMBERS
:------ | :-------- | :--------------------- | --------: | :------------------ | --------: | :------------------ | :------------------ | ----------:
H1 | HOTEL | Venue1 | 42 | 0001-02-03 04:05:06 | 123456.78 | null | null | null
SE1 | SPECIAL | Time Travel Convention | -1 | null | null | 2020-03-30 21:11:22 | 2020-03-30 00:00:00 | 0
db<>fiddle here
The typical way to create these tables in Oracle would be:
create table event_t (
event_id char(5) primary key not null,
event_type varchar2(20),
venue_mame varchar2(50),
no_of_guest number(10)
);
create table hotel_event_t (
event_date date,
price number(8,2),
event_id char(5),
constraint fk1 foreign key (event_id) references event_t (event_id)
);
create table special_event_t (
booking_date date,
end_date date,
menu_number number(2),
reservation_id char(5),
constraint fk2 foreign key (reservation_id)
references reservation_t (reservation_id),
event_id char(5),
constraint fk3 foreign key (event_id) references event_t (event_id)
);

Does Foreign Key constraint need to include NOT EQUAL to sibling Foreign Key?

I am new to SQL and Postgresql. I am trying to better understand how a foreign key constraint works with primary key of parent table.
Here's my current setup for two tables. I am trying to mimic an ISA relationship where echecks IS-A payment.
Table "public.payments"
Column | Type | Modifiers
pid | integer | not null default nextval('payments_pid_seq'::regclass)
street | character varying(80) |
zip | integer |
Indexes:
"payments_pkey" PRIMARY KEY, btree (pid)
Referenced by:
TABLE "cards" CONSTRAINT "cards_pid_fkey" FOREIGN KEY (pid) REFERENCES payments(pid)
TABLE "echecks" CONSTRAINT "echecks_pid_fkey" FOREIGN KEY (pid) REFERENCES payments(pid)
Table "public.echecks"
Column | Type | Modifiers
rtgacctnum | bigint |
accttype | character varying(80) |
nameonacct | character varying(80) |
pid | integer | not null default nextval('payments_pid_seq'::regclass)
Foreign-key constraints:
"echecks_pid_fkey" FOREIGN KEY (pid) REFERENCES payments(pid)
Table "public.cards"
Column | Type | Modifiers
pid | integer | not null default nextval('cards_pid_seq'::regclass)
cnum | bigint |
nameoncard | character varying(80) |
Foreign-key constraints:
"cards_pid_fkey" FOREIGN KEY (pid) REFERENCES payments(pid)
With this current setup, I am not able to prevent Echecks and Cards from inheriting the same pid from payments. I want Echecks to use the next number available pid from Payments, and not be the same pid in Cards.
Simplified version of what I would like to have happen:
Payments(pid, pay_type):
1, paypal
2, echeck
3, credit card
4, echeck
Echecks(fk_pid, acct_name)
2, susy
4, bob
Cards(fk_pid, card_name)
3, john
Instead, Echecks is just assigning on insertion:
1, susy
2, bob
And Cards assigns:
1, john
What is the best way to setup constraints on the foreign keys to insure it's being assigned a unique pid from Payments?
Echecks is not "grabbing" any value. You're supposed to insert a value into it that you want to appear there. So your real problem lies within insert logic that you didn't include in your post.

Need help optimizing a MySQL query - JOINs not using the correct indexes

I have this query below that I've rewritten a dozen different ways, yet I am unable to get it optimized and loaded in under 8 seconds. If I can get it to 2s, that would be good. 1s or less would be optimal.
This query retrieves a list of books that are currently available for sale or trade, and performs a bit of filtering. This query takes about 9-10 seconds.
SELECT
listing.for_sale,
listing.for_trade,
MIN(listing.price) AS from_price,
MAX(listing.price) AS to_price,
IF (NOW() > CONVERT_TZ(listing.date_sale_expiration, '+00:00', '-7:00'), 1, 0) AS expired,
COUNT(listing.book_id) AS 'listing_count',
book.id AS 'book_id',
book.title AS 'book_title',
book.date_released AS 'date_released',
book.publisher AS 'publisher',
book.photo_cover AS 'photo_cover',
publisher.name AS 'publisher_name',
COALESCE((SELECT COUNT(*) FROM listing l1 WHERE l1.book_id = book.id AND l1.status IN ('in_active_deal', 'complete')), 0) AS 'number_sold',
(SELECT 1 FROM listing l2 WHERE l2.status = 'available' AND l2.book_id = book.id AND l2.member_id = 1234 LIMIT 1) AS 'hasListing',
(SELECT 1 FROM wishlist w1 WHERE w1.book_id = book.id AND w1.member_id = 1234 LIMIT 1) AS 'hasWishlist'
FROM listing
INNER JOIN member ON
listing.member_id = member.id
AND member.transaction_limit <> 0
AND member.banned <> 1
AND member.date_last_login > DATE_SUB(CURDATE(), INTERVAL 120 DAY)
INNER JOIN book ON
listing.book_id = book.id
AND book.released = 1
INNER JOIN publisher ON
book.publisher_id = publisher.id
WHERE
listing.type = 'book'
AND listing.status = 'available'
AND (listing.for_trade = 1 OR (listing.for_sale = 1 AND NOW() < COALESCE(CONVERT_TZ(listing.date_sale_expiration, '+00:00', '-7:00'), 0)))
AND (
EXISTS (SELECT 1 FROM listing l3 LEFT JOIN book b ON l3.book_id = b.id WHERE l3.member_id = 1234 AND b.publisher_id = book.publisher_id AND l3.status = 'available' AND l3.type = 'book' AND (l3.for_trade = 1 OR (l3.for_sale = 1 AND NOW() < COALESCE(CONVERT_TZ(l3.date_sale_expiration, '+00:00', '-7:00'), 0))) LIMIT 1)
OR member.publisher_only <> 1
OR member.id = 1234
)
AND (
EXISTS (SELECT 1 FROM wishlist w WHERE w.member_id = member.id AND w.type = 'book' AND (w.type, w.book_id) IN (SELECT l4.type, l4.book_id FROM listing l4 WHERE 1234 = l4.member_id AND l4.status = 'available' AND (l4.for_trade = 1 OR (l4.for_sale = 1 AND NOW() < COALESCE(DATE_SUB(l4.date_sale_expiration, INTERVAL 7 HOUR), 0)))) LIMIT 1)
OR member.wishlist_only <> 1
OR member.id = 1234
)
GROUP BY
book.id
ORDER BY
book.date_released DESC
LIMIT 30;
These are my tables:
CREATE TABLE `listing` (
`id` int(10) unsigned NOT NULL auto_increment,
`member_id` int(10) unsigned NOT NULL,
`type` enum('book','audiobook','accessory') NOT NULL,
`book_id` int(10) unsigned default NULL,
`audiobook_id` int(10) unsigned default NULL,
`accessory_id` int(10) unsigned default NULL,
`date_created` datetime NOT NULL,
`date_modified` datetime NOT NULL,
`date_sale_expiration` datetime default NULL,
`status` enum('available','in_active_deal','complete','deleted') NOT NULL default 'available',
`for_sale` tinyint(1) unsigned NOT NULL default '0',
`for_trade` tinyint(1) unsigned NOT NULL default '0',
`price` decimal(10,2) default NULL,
`condition` tinyint(1) unsigned default NULL,
`notes` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `ix_accessory` (`accessory_id`,`member_id`,`type`,`status`),
KEY `ix_book` (`book_id`,`member_id`,`type`,`status`),
KEY `ix_member` (`member_id`,`status`,`date_created`),
KEY `ix_audiobook` (`audiobook_id`,`member_id`,`type`,`status`),
KEY `ix_status` (`status`,`accessory_id`,`for_trade`,`member_id`)
) ENGINE=MyISAM AUTO_INCREMENT=281724 DEFAULT CHARSET=utf8
CREATE TABLE `member` (
`id` int(10) unsigned NOT NULL auto_increment,
`email` varchar(200) NOT NULL,
`screen_name` varchar(25) default NULL,
`date_last_login` datetime default NULL,
`wishlist_only` tinyint(1) unsigned NOT NULL default '1',
`platform_only` tinyint(1) unsigned NOT NULL default '0',
`transaction_limit` smallint(6) NOT NULL default '5',
`banned` tinyint(1) unsigned NOT NULL default '0',
`notes` text,
PRIMARY KEY (`id`),
KEY `ix_email` (`email`),
KEY `ix_screen_name` (`screen_name`),
KEY `ix_transaction_limit` (`transaction_limit`)
) ENGINE=MyISAM AUTO_INCREMENT=50842 DEFAULT CHARSET=utf8
CREATE TABLE `publisher` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(128) NOT NULL,
`date_updated` datetime default NULL,
PRIMARY KEY (`id`),
KEY `ix_name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=129 DEFAULT CHARSET=utf8
CREATE TABLE `book` (
`id` int(10) unsigned NOT NULL auto_increment,
`publisher_id` int(10) unsigned default NULL,
`name` varchar(128) NOT NULL,
`description` text,
`keywords` varchar(200) default NULL,
`date_released` varchar(10) default NULL,
`genre` varchar(50) default NULL,
`subgenre` varchar(50) default NULL,
`author` varchar(100) default NULL,
`date_updated` datetime default NULL,
`photo_cover` varchar(50) default NULL,
`weight_oz` decimal(7,2) default NULL,
`released` tinyint(2) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `ix_genre` (`genre`),
KEY `ix_name` (`name`),
KEY `ix_released` (`released`,`date_released`),
KEY `ix_keywords` (`keywords`)
) ENGINE=MyISAM AUTO_INCREMENT=87329 DEFAULT CHARSET=utf8
CREATE TABLE `wishlist` (
`id` int(10) unsigned NOT NULL auto_increment,
`member_id` int(10) unsigned NOT NULL,
`type` enum('book','audiobook','accessory') NOT NULL,
`book_id` int(10) unsigned default NULL,
`audiobook_id` int(10) unsigned default NULL,
`accessory_id` int(10) unsigned default NULL,
`date_created` datetime NOT NULL,
`date_modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_accessory` (`accessory_id`,`member_id`,`type`),
KEY `ix_book` (`book_id`,`member_id`,`type`),
KEY `ix_member_accessory` (`member_id`,`accessory_id`),
KEY `ix_member_date_created` (`member_id`,`date_created`),
KEY `ix_member_book` (`member_id`,`book_id`),
KEY `ix_member_audiobook` (`member_id`,`audiobook_id`),
KEY `ix_audiobook` (`audiobook_id`,`member_id`,`type`)
) ENGINE=MyISAM AUTO_INCREMENT=241886 DEFAULT CHARSET=utf8
And here is the result when I run EXPLAIN:
+----+--------------------+-----------+----------------+---------------------------------------------------------------------------------------+----------------------+---------+------------------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------+----------------+---------------------------------------------------------------------------------------+----------------------+---------+------------------------------------+-------+----------------------------------------------+
| 1 | PRIMARY | member | range | PRIMARY,ix_transaction_limit | ix_transaction_limit | 2 | NULL | 19617 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | listing | ref | ix_game,ix_member,ix_status | ix_member | 5 | live_database001.member.id,const | 7 | Using where |
| 1 | PRIMARY | book | eq_ref | PRIMARY,ix_released | PRIMARY | 4 | live_database001.listing.book_id | 1 | Using where |
| 1 | PRIMARY | publisher | eq_ref | PRIMARY | PRIMARY | 4 | live_database001.book.publisher_id | 1 | |
| 6 | DEPENDENT SUBQUERY | w | ref | ix_member_accessory,ix_member_date_created,ix_member_book,ix_member_publisher | ix_member_accessory | 4 | live_database001.member.id | 6 | Using where |
| 7 | DEPENDENT SUBQUERY | l4 | index_subquery | ix_book,ix_member,ix_status | ix_book | 11 | func,const,func,const | 1 | Using where |
| 5 | DEPENDENT SUBQUERY | l3 | ref | ix_book,ix_member,ix_status | ix_member | 5 | const,const | 63 | Using where |
| 5 | DEPENDENT SUBQUERY | b | eq_ref | PRIMARY | PRIMARY | 4 | live_database001.l3.book_id | 1 | Using where |
| 4 | DEPENDENT SUBQUERY | w1 | ref | ix_book,ix_member_accessory,ix_member_date_created,ix_member_game,ix_member_publisher | ix_book | 9 | func,const | 1 | Using where; Using index |
| 3 | DEPENDENT SUBQUERY | l2 | ref | ix_book,ix_member,ix_status | ix_book | 9 | func,const | 1 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | l1 | ref | ix_book,ix_status | ix_book | 5 | func | 10 | Using where; Using index |
+----+--------------------+-----------+----------------+--------------------------------------------------------------------------------------+----------------------+---------+------------------------------------+-------+----------------------------------------------+
This brings me to a couple questions:
1. The member table is using ix_transaction_limit, and as a result is searching through 19k+ rows. Since I am specifying a member.id, shouldn't this be using PRIMARY and shouldn't the rows be 1? How can I fix this?
2. How does the key_len affect the performance?
3. I've seen other complex queries which dealt with 100's of millions of rows take less time. How is it that only 19k rows are taking so long?
(I'm still very green with MySQL Optimization, so I'd really love to understand the how's & why's)
Any suggestions small or big is greatly appreciated, thank you in advance!
Not sure what transaction limit does but at a guess it seems like a strange choice to have an index on. What might help is an index on date_last_login. At the moment the query is filtering member and then joining listing to it - ie. its going through all the member records with the appropriate transaction limit and using the member id to find the listing.
After dropping the index on the member table, I was still having the same problems. In fact, that made it even worse. So my ultimate solution was to completely re-write the query from scratch.
And consequently, changing the order in the conditionals made a big difference as well. So moving the and member_id = 1234 and the and wishlish_only <> 1 up above the subquery was a huge improvement.
Thanks for all your help!