MySQL: Find records in one table that are not in another - revised
electrictoolbox.com
electrictoolbox.com
This puts into context all the people complaining about SQL and relational databases, and how great key-value stores are. Perhaps some of the sturm und drang is over the fact that, while SQL people admittedly may have little experience with Hadoop or other non-relational processing and storage, sounds like some HN folks have actually had little experience with the SQL they are disparaging.
Joe Celko's SQL for Smarties is full of great explanations of how to really use SQL, and is worth picking up if you want to see what SQL can really do and work around it's (many) warts. http://www.amazon.com/Joe-Celkos-SQL-Smarties-Programming/dp...
It's all implementation details. I've worked with databases where a NOT EXISTS would run a query for every source row where as an outer join would run through once doing the join and was therefore faster.
The basic rule is, don't ask the database to do more than is necessary. Don't include tables in the FROM clause that won't be used downstream (GROUP BY, HAVING, SELECT, ORDER BY). If you only need it in the WHERE clause, try using a correlated subquery (ie, EXISTS).
Another example for finding duplicates:
select * from table1 as a where exists (
select * from table1 as b
group by key1
having count(*) > 1
and a.key1 = b.key1
)
(Not sure if this syntax works on MySQL, but there's the idea.) select distinct a.*
from table1 a join table1 b
on (a.key1 = b.key1 and a.PRIMARY_KEY != b.PRIMARY_KEY)
Yours took 0.59 sec, and mine was 0.10 sec (on some random test data).In general MySql doesn't do so well with subqueries - it likes them as joins. But in this case I think any database would be faster with my query (anyone care to test)?
And when I say joins instead of subqueries I mean:
select *
from table1 as a join
(select key1 from table1 as b
group by key1
having count(*) > 1
) c
on (a.key1 = c.key1)
Which took 0.00 sec (must say I was not expecting that).In the second example, if key1 is unique and the database knows it, the optimizer should be able to determine that c returns no records, and therefore the outer query returns no records as well. It bypasses execution entirely, thus 0.00 sec.
If key1 is not unique, or it is unique but the database doesn't know about it, that is impressive.
SELECT * FROM content c WHERE c.content_id NOT IN ( SELECT c2t.content_id FROM content_to_tags c2t )
Edit: I stand corrected.
If using sub-selects is faster than JOINS on what I would assume is indexed data, your query-optimizer is doing something horribly, horribly wrong.
And given how everyone complains about MySQL's support for sub-selects and the performance of those, I can't even start to comprehend how bad and inefficiently it implements JOINs if sub-selects are indeed faster.
Yeah, I think I'll just stick to SQL Server for now.
Maybe I'm missing something crucial, but that doesn't seem to make much sense for me from a data-access perspective.