Re: Optimising LIMITs
| From: | Pavel Lobovich | Date: | Tue, 02 Mar 2004 07:20:03 +0000 |
| Subject: | Re: Optimising LIMITs | ||
| References: | 1 | Groups: | php.db |
| Request: | Send a blank email to php-db+get-33249@lists.php.net to get a copy of this message | ||
Hi Richard!
Step 1
---------------
Is it right?
1.
threadid value is unique.
2. threadid value is auto_increment.
3. if threadid(2) > threadid(1) => created(2) >
created(1).
You can do the following:
1. Create the index on two fields: (boardid, status)
2. ALTER TABLE board ORDER BY threadid DESC;
Here is new query to fetch a block of records:
SELECT * FROM board WHERE boardid = 1 AND status =
"L" LIMIT
100,50
Step 2
----------------
The average size of row in your table is 128,000,000 / 190,000 ~= 675
bytes.
Split your table in two tables, like:
CREATE TABLE boardinfo
( threadid INT(4) UNSIGNED AUTO_INCREMENT,
PRIMARY KEY( threadid ),
boardid INT(4) UNSIGNED,
status ENUM( 'L', '....' ),
created TIMESTAMP
... (all fixed fields )
)
ALTER TABLE boardinfo CREATE INDEX main (boardid,status`)
ALTER TABLE boardinfo ORDER BY threadid DESC
CREATE TABLE boarddata (
threadid_ref INT(4) UNSIGNED,
PRIMARY KEY ( threadid_ref ),
threaddata LONGTEXT
)
Here is your query after:
SELECT * FROM boardinfo LEFT JOIN boarddata ON threadid =
threadid_ref WHERE boardid = 1 AND status = "L"
LIMIT 100,50
Sorry for my englist.
Best regards, Pavel
> Hi all,
>
> I have what is probably a quite standard question and would love to
> know how you would all approach this scenario:
>
> I have a table in a database that has approx. 190,000 records in it.
> The table is currently 128MB in size and I'm happy that it is well
> constructed with no data duplication and sensible indexes.
>
> I'm using MySQL 3.28.58. and my question is about querying this volume
> of data efficiently.
>
> The table holds forum threads (several years worth) so a common query
> running on the table is to bring back the top 50 or 100 threads from a
> board within the forum.
>
> To do this I'm using a LIMIT on my query and for the paging through
> the data (i.e. the first 100 threads, the next 100, etc) I use the
> LIMIT n,x syntax. Threads are sorted by date (most recent to the top).
>
> This is fine and it works well but I'm concerned it's not the most
> efficient way to do this because the use of LIMIT is causing the
> whole table to be scanned each time.
>
> Here is a typical (simplified) query:
>
> SELECT *
> FROM thread
> WHERE
> thread.status='L' AND
> thread.boardid=1
> ORDER BY created DESC
> LIMIT 100,50
>
> This takes over 1.02 seconds to process.
>
> Running an EXPLAIN on my query shows that it's using one key
> (boardid), but in the Extra field it shows it is having to use a
> filesort on the data. 5701 rows were used in order to bring back the
> final 50 - that's every single thread for this board.
>
> What I'm trying to figure out is a more efficient way of selecting a
> block of 50 or 100 records from any point in my table without MySQL
> needing to sort/check them all first.
>
> One thought I did have was that the Primary Key on my table is called
> threadid - and I thought that instead of bring back the data in my
> original query, I could collect nothing but the thread IDs and then
> use a separate query that does something like: "SELECT * FROM thread
> WHERE threadid IN (...)" (where ... = all of the IDs previously
> selected). Would the fact that threadid is my primary key make the
> original LIMIT/sort faster?
>
> Any thoughts appreciated.
>
> --
> Best regards,
> Richard Davey
> http://www.phpcommunity.org/wiki/296.html